blob: e6618b1d5182ca23879ac040cf5a7b6c83357aee [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
Éric Araujoec177c12012-06-24 03:27:43 -040021_INSTALL_SCHEMES = {
22 'posix_prefix': {
23 'stdlib': '{installed_base}/lib/python{py_version_short}',
24 'platstdlib': '{platbase}/lib/python{py_version_short}',
25 'purelib': '{base}/lib/python{py_version_short}/site-packages',
26 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
27 'include':
28 '{installed_base}/include/python{py_version_short}{abiflags}',
29 'platinclude':
30 '{installed_platbase}/include/python{py_version_short}{abiflags}',
31 'scripts': '{base}/bin',
32 'data': '{base}',
33 },
34 'posix_home': {
35 'stdlib': '{installed_base}/lib/python',
36 'platstdlib': '{base}/lib/python',
37 'purelib': '{base}/lib/python',
38 'platlib': '{base}/lib/python',
39 'include': '{installed_base}/include/python',
40 'platinclude': '{installed_base}/include/python',
41 'scripts': '{base}/bin',
42 'data': '{base}',
43 },
44 'nt': {
45 'stdlib': '{installed_base}/Lib',
46 'platstdlib': '{base}/Lib',
47 'purelib': '{base}/Lib/site-packages',
48 'platlib': '{base}/Lib/site-packages',
49 'include': '{installed_base}/Include',
50 'platinclude': '{installed_base}/Include',
51 'scripts': '{base}/Scripts',
52 'data': '{base}',
53 },
INADA Naokia8f8d5b2017-06-29 00:31:53 +090054 # NOTE: When modifying "purelib" scheme, update site._get_path() too.
Éric Araujoec177c12012-06-24 03:27:43 -040055 'nt_user': {
56 'stdlib': '{userbase}/Python{py_version_nodot}',
57 'platstdlib': '{userbase}/Python{py_version_nodot}',
58 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
59 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
60 'include': '{userbase}/Python{py_version_nodot}/Include',
Steve Dower17be5142015-02-14 09:50:59 -080061 'scripts': '{userbase}/Python{py_version_nodot}/Scripts',
Éric Araujoec177c12012-06-24 03:27:43 -040062 'data': '{userbase}',
63 },
64 'posix_user': {
65 'stdlib': '{userbase}/lib/python{py_version_short}',
66 'platstdlib': '{userbase}/lib/python{py_version_short}',
67 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
68 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
69 'include': '{userbase}/include/python{py_version_short}',
70 'scripts': '{userbase}/bin',
71 'data': '{userbase}',
72 },
73 'osx_framework_user': {
74 'stdlib': '{userbase}/lib/python',
75 'platstdlib': '{userbase}/lib/python',
76 'purelib': '{userbase}/lib/python/site-packages',
77 'platlib': '{userbase}/lib/python/site-packages',
78 'include': '{userbase}/include',
79 'scripts': '{userbase}/bin',
80 'data': '{userbase}',
81 },
82 }
Tarek Ziadéedacea32010-01-29 11:41:03 +000083
Éric Araujoec177c12012-06-24 03:27:43 -040084_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
85 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +020086
Vinay Sajip7ded1f02012-05-26 03:45:29 +010087 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +020088 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000089_PY_VERSION = sys.version.split()[0]
Serhiy Storchaka885bdc42016-02-11 13:10:36 +020090_PY_VERSION_SHORT = '%d.%d' % sys.version_info[:2]
91_PY_VERSION_SHORT_NO_DOT = '%d%d' % sys.version_info[:2]
Tarek Ziadéedacea32010-01-29 11:41:03 +000092_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010093_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000094_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010095_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000096_CONFIG_VARS = None
97_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000098
Tarek Ziade1231a4e2011-05-19 13:07:25 +020099
Victor Stinnerb103a932010-10-12 22:23:23 +0000100def _safe_realpath(path):
101 try:
102 return realpath(path)
103 except OSError:
104 return path
105
Victor Stinner171ba052010-03-12 14:20:59 +0000106if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000107 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000108else:
109 # sys.executable can be empty if argv[0] has been changed and Python is
110 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000111 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000112
Steve Dower65e4cb12014-11-22 12:54:57 -0800113if (os.name == 'nt' and
114 _PROJECT_BASE.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
Victor Stinnerb103a932010-10-12 22:23:23 +0000115 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000116
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200117# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200118if "_PYTHON_PROJECT_BASE" in os.environ:
119 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200120
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100121def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000122 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100123 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000124 return True
125 return False
126
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100127_sys_home = getattr(sys, '_home', None)
Steve Dower65e4cb12014-11-22 12:54:57 -0800128if (_sys_home and os.name == 'nt' and
129 _sys_home.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
130 _sys_home = os.path.dirname(os.path.dirname(_sys_home))
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100131def is_python_build(check_home=False):
132 if check_home and _sys_home:
133 return _is_python_source_dir(_sys_home)
134 return _is_python_source_dir(_PROJECT_BASE)
135
136_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000137
138if _PYTHON_BUILD:
139 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400140 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
141 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000142
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200143
Éric Araujoec177c12012-06-24 03:27:43 -0400144def _subst_vars(s, local_vars):
145 try:
146 return s.format(**local_vars)
147 except KeyError:
148 try:
149 return s.format(**os.environ)
150 except KeyError as var:
Serhiy Storchaka5affd232017-04-05 09:37:24 +0300151 raise AttributeError('{%s}' % var) from None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000152
153def _extend_dict(target_dict, other_dict):
154 target_keys = target_dict.keys()
155 for key, value in other_dict.items():
156 if key in target_keys:
157 continue
158 target_dict[key] = value
159
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200160
Tarek Ziadéedacea32010-01-29 11:41:03 +0000161def _expand_vars(scheme, vars):
162 res = {}
163 if vars is None:
164 vars = {}
165 _extend_dict(vars, get_config_vars())
166
Éric Araujoec177c12012-06-24 03:27:43 -0400167 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168 if os.name in ('posix', 'nt'):
169 value = os.path.expanduser(value)
170 res[key] = os.path.normpath(_subst_vars(value, vars))
171 return res
172
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200173
Tarek Ziadéedacea32010-01-29 11:41:03 +0000174def _get_default_scheme():
175 if os.name == 'posix':
176 # the default scheme for posix is posix_prefix
177 return 'posix_prefix'
178 return os.name
179
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200180
INADA Naokia8f8d5b2017-06-29 00:31:53 +0900181# NOTE: site.py has copy of this function.
182# Sync it when modify this function.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000183def _getuserbase():
184 env_base = os.environ.get("PYTHONUSERBASE", None)
INADA Naokia8f8d5b2017-06-29 00:31:53 +0900185 if env_base:
186 return env_base
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200187
Tarek Ziadéedacea32010-01-29 11:41:03 +0000188 def joinuser(*args):
189 return os.path.expanduser(os.path.join(*args))
190
Tarek Ziadéedacea32010-01-29 11:41:03 +0000191 if os.name == "nt":
192 base = os.environ.get("APPDATA") or "~"
INADA Naokia8f8d5b2017-06-29 00:31:53 +0900193 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000194
INADA Naokia8f8d5b2017-06-29 00:31:53 +0900195 if sys.platform == "darwin" and sys._framework:
196 return joinuser("~", "Library", sys._framework,
197 "%d.%d" % sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000198
INADA Naokia8f8d5b2017-06-29 00:31:53 +0900199 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000200
201
202def _parse_makefile(filename, vars=None):
203 """Parse a Makefile-style file.
204
205 A dictionary containing name/value pairs is returned. If an
206 optional dictionary is passed in as the second argument, it is
207 used instead of a new dictionary.
208 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000209 # Regexes needed for parsing Makefile (and similar syntaxes,
210 # like old-style Setup files).
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200211 import re
R David Murray44b548d2016-09-08 13:59:53 -0400212 _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000213 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
214 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
215
216 if vars is None:
217 vars = {}
218 done = {}
219 notdone = {}
220
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000221 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000222 lines = f.readlines()
223
224 for line in lines:
225 if line.startswith('#') or line.strip() == '':
226 continue
227 m = _variable_rx.match(line)
228 if m:
229 n, v = m.group(1, 2)
230 v = v.strip()
231 # `$$' is a literal `$' in make
232 tmpv = v.replace('$$', '')
233
234 if "$" in tmpv:
235 notdone[n] = v
236 else:
237 try:
238 v = int(v)
239 except ValueError:
240 # insert literal `$'
241 done[n] = v.replace('$$', '$')
242 else:
243 done[n] = v
244
245 # do variable interpolation here
246 variables = list(notdone.keys())
247
Ronald Oussorend21886c2010-07-20 16:07:10 +0000248 # Variables with a 'PY_' prefix in the makefile. These need to
249 # be made available without that prefix through sysconfig.
250 # Special care is needed to ensure that variable expansion works, even
251 # if the expansion uses the name without a prefix.
252 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
253
Tarek Ziadéedacea32010-01-29 11:41:03 +0000254 while len(variables) > 0:
255 for name in tuple(variables):
256 value = notdone[name]
doko@ubuntu.comb2b12172016-01-11 21:41:40 +0100257 m1 = _findvar1_rx.search(value)
258 m2 = _findvar2_rx.search(value)
259 if m1 and m2:
260 m = m1 if m1.start() < m2.start() else m2
261 else:
262 m = m1 if m1 else m2
Tarek Ziadéedacea32010-01-29 11:41:03 +0000263 if m is not None:
264 n = m.group(1)
265 found = True
266 if n in done:
267 item = str(done[n])
268 elif n in notdone:
269 # get it on a subsequent round
270 found = False
271 elif n in os.environ:
272 # do it like make: fall back to environment
273 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000274
275 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200276 if (name.startswith('PY_') and
277 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000278 item = ""
279
280 elif 'PY_' + n in notdone:
281 found = False
282
283 else:
284 item = str(done['PY_' + n])
285
Tarek Ziadéedacea32010-01-29 11:41:03 +0000286 else:
287 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000288
Tarek Ziadéedacea32010-01-29 11:41:03 +0000289 if found:
290 after = value[m.end():]
291 value = value[:m.start()] + item + after
292 if "$" in after:
293 notdone[name] = value
294 else:
295 try:
296 value = int(value)
297 except ValueError:
298 done[name] = value.strip()
299 else:
300 done[name] = value
301 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000302
303 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200304 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000305
306 name = name[3:]
307 if name not in done:
308 done[name] = value
309
Tarek Ziadéedacea32010-01-29 11:41:03 +0000310 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200311 # bogus variable reference (e.g. "prefix=$/opt/python");
312 # just drop it since we can't deal
313 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000314 variables.remove(name)
315
Antoine Pitroudbec7802010-10-10 09:37:12 +0000316 # strip spurious spaces
317 for k, v in done.items():
318 if isinstance(v, str):
319 done[k] = v.strip()
320
Tarek Ziadéedacea32010-01-29 11:41:03 +0000321 # save the results in the global dictionary
322 vars.update(done)
323 return vars
324
Tarek Ziadéedacea32010-01-29 11:41:03 +0000325
Barry Warsawebbef6f2010-09-20 15:29:53 +0000326def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000327 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000328 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100329 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200330 if hasattr(sys, 'abiflags'):
331 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
332 else:
333 config_dir_name = 'config'
doko@ubuntu.com55532312016-06-14 08:55:19 +0200334 if hasattr(sys.implementation, '_multiarch'):
335 config_dir_name += '-%s' % sys.implementation._multiarch
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200336 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000337
Zachary Warec4b53af2016-09-09 17:59:49 -0700338
Xavier de Gaye92dec542016-09-11 22:22:24 +0200339def _get_sysconfigdata_name():
340 return os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
341 '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
342 abi=sys.abiflags,
343 platform=sys.platform,
344 multiarch=getattr(sys.implementation, '_multiarch', ''),
345 ))
Zachary Warec4b53af2016-09-09 17:59:49 -0700346
347
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200348def _generate_posix_vars():
349 """Generate the Python module containing build-time variables."""
350 import pprint
351 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000352 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000353 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000354 try:
355 _parse_makefile(makefile, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200356 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000357 msg = "invalid Python installation: unable to open %s" % makefile
358 if hasattr(e, "strerror"):
359 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200360 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000361 # load the installed pyconfig.h:
362 config_h = get_config_h_filename()
363 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000364 with open(config_h) as f:
365 parse_config_h(f, vars)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200366 except OSError as e:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000367 msg = "invalid Python installation: unable to open %s" % config_h
368 if hasattr(e, "strerror"):
369 msg = msg + " (%s)" % e.strerror
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200370 raise OSError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000371 # On AIX, there are wrong paths to the linker scripts in the Makefile
372 # -- these paths are relative to the Python source, but when installed
373 # the scripts are in another directory.
374 if _PYTHON_BUILD:
Antoine Pitrou0abb2182013-10-19 22:05:05 +0200375 vars['BLDSHARED'] = vars['LDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200376
Trent Nelsonee528cc2012-10-17 04:23:50 -0400377 # There's a chicken-and-egg situation on OS X with regards to the
378 # _sysconfigdata module after the changes introduced by #15298:
379 # get_config_vars() is called by get_platform() as part of the
380 # `make pybuilddir.txt` target -- which is a precursor to the
381 # _sysconfigdata.py module being constructed. Unfortunately,
382 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400383 # to import _sysconfigdata, which we won't have built yet. In order
384 # for _init_posix() to work, if we're on Darwin, just mock up the
385 # _sysconfigdata module manually and populate it with the build vars.
386 # This is more than sufficient for ensuring the subsequent call to
387 # get_platform() succeeds.
Xavier de Gaye92dec542016-09-11 22:22:24 +0200388 name = _get_sysconfigdata_name()
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400389 if 'darwin' in sys.platform:
Brett Cannonf15a59f2013-06-15 14:32:11 -0400390 import types
391 module = types.ModuleType(name)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400392 module.build_time_vars = vars
393 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000394
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200395 pybuilddir = 'build/lib.%s-%s' % (get_platform(), _PY_VERSION_SHORT)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400396 if hasattr(sys, "gettotalrefcount"):
397 pybuilddir += '-pydebug'
398 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400399 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400400
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400401 with open(destfile, 'w', encoding='utf8') as f:
402 f.write('# system configuration generated and used by'
403 ' the sysconfig module\n')
404 f.write('build_time_vars = ')
405 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400406
Trent Nelsonc101bf32012-10-16 08:13:12 -0400407 # Create file used for sys.path fixup -- see Modules/getpath.c
408 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
409 f.write(pybuilddir)
410
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200411def _init_posix(vars):
412 """Initialize the module as appropriate for POSIX systems."""
413 # _sysconfigdata is generated at build time, see _generate_posix_vars()
Zachary Warec4b53af2016-09-09 17:59:49 -0700414 name = _get_sysconfigdata_name()
doko@ubuntu.com55532312016-06-14 08:55:19 +0200415 _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
416 build_time_vars = _temp.build_time_vars
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200417 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200418
Tarek Ziadéedacea32010-01-29 11:41:03 +0000419def _init_non_posix(vars):
420 """Initialize the module as appropriate for NT"""
421 # set basic install directories
422 vars['LIBDEST'] = get_path('stdlib')
423 vars['BINLIBDEST'] = get_path('platstdlib')
424 vars['INCLUDEPY'] = get_path('include')
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700425 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000426 vars['EXE'] = '.exe'
427 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000428 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000429
430#
431# public APIs
432#
433
Tarek Ziadébd797682010-02-02 23:16:13 +0000434
435def parse_config_h(fp, vars=None):
436 """Parse a config.h-style file.
437
438 A dictionary containing name/value pairs is returned. If an
439 optional dictionary is passed in as the second argument, it is
440 used instead of a new dictionary.
441 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000442 if vars is None:
443 vars = {}
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200444 import re
Tarek Ziadébd797682010-02-02 23:16:13 +0000445 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
446 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
447
448 while True:
449 line = fp.readline()
450 if not line:
451 break
452 m = define_rx.match(line)
453 if m:
454 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200455 try:
456 v = int(v)
457 except ValueError:
458 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000459 vars[n] = v
460 else:
461 m = undef_rx.match(line)
462 if m:
463 vars[m.group(1)] = 0
464 return vars
465
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200466
Tarek Ziadébd797682010-02-02 23:16:13 +0000467def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000468 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000469 if _PYTHON_BUILD:
470 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100471 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000472 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100473 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000474 else:
475 inc_dir = get_path('platinclude')
476 return os.path.join(inc_dir, 'pyconfig.h')
477
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200478
Tarek Ziadéedacea32010-01-29 11:41:03 +0000479def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000480 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400481 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200482
Tarek Ziadéedacea32010-01-29 11:41:03 +0000483
484def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000485 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400486 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200487
Tarek Ziadéedacea32010-01-29 11:41:03 +0000488
489def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000490 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000491
492 ``scheme`` is the install scheme name. If not provided, it will
493 return the default scheme for the current platform.
494 """
495 if expand:
496 return _expand_vars(scheme, vars)
497 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400498 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200499
Tarek Ziadéedacea32010-01-29 11:41:03 +0000500
501def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000502 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000503
504 ``scheme`` is the install scheme name.
505 """
506 return get_paths(scheme, vars, expand)[name]
507
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200508
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509def get_config_vars(*args):
510 """With no arguments, return a dictionary of all configuration
511 variables relevant for the current platform.
512
513 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700514 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000515
516 With arguments, return a list of values that result from looking up
517 each argument in the configuration variable dictionary.
518 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000519 global _CONFIG_VARS
520 if _CONFIG_VARS is None:
521 _CONFIG_VARS = {}
522 # Normalized versions of prefix and exec_prefix are handy to have;
523 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400524 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000525 _CONFIG_VARS['prefix'] = _PREFIX
526 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
527 _CONFIG_VARS['py_version'] = _PY_VERSION
528 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
Serhiy Storchaka885bdc42016-02-11 13:10:36 +0200529 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100530 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000531 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100532 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000533 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000534 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000535 try:
536 _CONFIG_VARS['abiflags'] = sys.abiflags
537 except AttributeError:
538 # sys.abiflags may not be defined on all platforms.
539 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000540
Jesus Cea4791a242012-10-05 03:15:39 +0200541 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000542 _init_non_posix(_CONFIG_VARS)
543 if os.name == 'posix':
544 _init_posix(_CONFIG_VARS)
Barry Warsaw87b96372013-11-22 11:08:05 -0500545 # For backward compatibility, see issue19555
546 SO = _CONFIG_VARS.get('EXT_SUFFIX')
547 if SO is not None:
548 _CONFIG_VARS['SO'] = SO
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000549 # Setting 'userbase' is done below the call to the
550 # init function to enable using 'get_config_var' in
551 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100552 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000553
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100554 # Always convert srcdir to an absolute path
555 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
556 if os.name == 'posix':
557 if _PYTHON_BUILD:
558 # If srcdir is a relative path (typically '.' or '..')
559 # then it should be interpreted relative to the directory
560 # containing Makefile.
561 base = os.path.dirname(get_makefile_filename())
562 srcdir = os.path.join(base, srcdir)
563 else:
564 # srcdir is not meaningful since the installation is
565 # spread about the filesystem. We choose the
566 # directory containing the Makefile since we know it
567 # exists.
568 srcdir = os.path.dirname(get_makefile_filename())
569 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000570
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700571 # OS X platforms require special customization to handle
572 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000573 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700574 import _osx_support
575 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000576
577 if args:
578 vals = []
579 for name in args:
580 vals.append(_CONFIG_VARS.get(name))
581 return vals
582 else:
583 return _CONFIG_VARS
584
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200585
Tarek Ziadéedacea32010-01-29 11:41:03 +0000586def get_config_var(name):
587 """Return the value of a single variable using the dictionary returned by
588 'get_config_vars()'.
589
590 Equivalent to get_config_vars().get(name)
591 """
Barry Warsaw197a7702013-11-21 18:57:14 -0500592 if name == 'SO':
593 import warnings
Serhiy Storchakaeaec3592013-11-26 17:08:24 +0200594 warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000595 return get_config_vars().get(name)
596
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200597
Tarek Ziadéedacea32010-01-29 11:41:03 +0000598def get_platform():
599 """Return a string that identifies the current platform.
600
601 This is used mainly to distinguish platform-specific build directories and
602 platform-specific built distributions. Typically includes the OS name
603 and version and the architecture (as supplied by 'os.uname()'),
604 although the exact information included depends on the OS; eg. for IRIX
605 the architecture isn't particularly important (IRIX only runs on SGI
606 hardware), but for Linux the kernel version isn't particularly
607 important.
608
609 Examples of returned values:
610 linux-i586
611 linux-alpha (?)
612 solaris-2.6-sun4u
613 irix-5.3
614 irix64-6.2
615
616 Windows will return one of:
617 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
618 win-ia64 (64bit Windows on Itanium)
619 win32 (all others - specifically, sys.platform is returned)
620
621 For other non-POSIX platforms, currently just returns 'sys.platform'.
622 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000623 if os.name == 'nt':
624 # sniff sys.version for architecture.
625 prefix = " bit ("
626 i = sys.version.find(prefix)
627 if i == -1:
628 return sys.platform
629 j = sys.version.find(")", i)
630 look = sys.version[i+len(prefix):j].lower()
631 if look == 'amd64':
632 return 'win-amd64'
633 if look == 'itanium':
634 return 'win-ia64'
635 return sys.platform
636
637 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700638 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000639 return sys.platform
640
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200641 # Set for cross builds explicitly
642 if "_PYTHON_HOST_PLATFORM" in os.environ:
643 return os.environ["_PYTHON_HOST_PLATFORM"]
644
Tarek Ziadéedacea32010-01-29 11:41:03 +0000645 # Try to distinguish various flavours of Unix
646 osname, host, release, version, machine = os.uname()
647
648 # Convert the OS name to lowercase, remove '/' characters
649 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
650 osname = osname.lower().replace('/', '')
651 machine = machine.replace(' ', '_')
652 machine = machine.replace('/', '-')
653
654 if osname[:5] == "linux":
655 # At least on Linux/Intel, 'machine' is the processor --
656 # i386, etc.
657 # XXX what about Alpha, SPARC, etc?
658 return "%s-%s" % (osname, machine)
659 elif osname[:5] == "sunos":
660 if release[0] >= "5": # SunOS 5 == Solaris 2
661 osname = "solaris"
662 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100663 # We can't use "platform.architecture()[0]" because a
664 # bootstrap problem. We use a dict to get an error
665 # if some suspicious happens.
666 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100667 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000668 # fall through to standard osname-release-machine representation
669 elif osname[:4] == "irix": # could be "irix64"!
670 return "%s-%s" % (osname, release)
671 elif osname[:3] == "aix":
672 return "%s-%s.%s" % (osname, version, release)
673 elif osname[:6] == "cygwin":
674 osname = "cygwin"
Christian Heimes8c9cd5a2013-10-12 00:24:55 +0200675 import re
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200676 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000677 m = rel_re.match(release)
678 if m:
679 release = m.group()
680 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700681 import _osx_support
682 osname, release, machine = _osx_support.get_platform_osx(
683 get_config_vars(),
684 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000685
686 return "%s-%s-%s" % (osname, release, machine)
687
688
689def get_python_version():
690 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000691
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200692
Tarek Ziadéa7514992010-05-25 09:44:36 +0000693def _print_dict(title, data):
694 for index, (key, value) in enumerate(sorted(data.items())):
695 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200696 print('%s: ' % (title))
697 print('\t%s = "%s"' % (key, value))
698
Tarek Ziadéa7514992010-05-25 09:44:36 +0000699
700def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000701 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200702 if '--generate-posix-vars' in sys.argv:
703 _generate_posix_vars()
704 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200705 print('Platform: "%s"' % get_platform())
706 print('Python version: "%s"' % get_python_version())
707 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200708 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000709 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200710 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000711 _print_dict('Variables', get_config_vars())
712
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200713
Tarek Ziadéa7514992010-05-25 09:44:36 +0000714if __name__ == '__main__':
715 _main()