blob: 2f5f7404fff5c80a1e6e5f50213d025a843ab5c5 [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 re
5import sys
Florent Xiclunaa4707382010-03-11 00:05:17 +00006from os.path import pardir, realpath
Tarek Ziadéedacea32010-01-29 11:41:03 +00007
Barry Warsawebbef6f2010-09-20 15:29:53 +00008__all__ = [
9 'get_config_h_filename',
10 'get_config_var',
11 'get_config_vars',
12 'get_makefile_filename',
13 'get_path',
14 'get_path_names',
15 'get_paths',
16 'get_platform',
17 'get_python_version',
18 'get_scheme_names',
19 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020020]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000021
Éric Araujoec177c12012-06-24 03:27:43 -040022_INSTALL_SCHEMES = {
23 'posix_prefix': {
24 'stdlib': '{installed_base}/lib/python{py_version_short}',
25 'platstdlib': '{platbase}/lib/python{py_version_short}',
26 'purelib': '{base}/lib/python{py_version_short}/site-packages',
27 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
28 'include':
29 '{installed_base}/include/python{py_version_short}{abiflags}',
30 'platinclude':
31 '{installed_platbase}/include/python{py_version_short}{abiflags}',
32 'scripts': '{base}/bin',
33 'data': '{base}',
34 },
35 'posix_home': {
36 'stdlib': '{installed_base}/lib/python',
37 'platstdlib': '{base}/lib/python',
38 'purelib': '{base}/lib/python',
39 'platlib': '{base}/lib/python',
40 'include': '{installed_base}/include/python',
41 'platinclude': '{installed_base}/include/python',
42 'scripts': '{base}/bin',
43 'data': '{base}',
44 },
45 'nt': {
46 'stdlib': '{installed_base}/Lib',
47 'platstdlib': '{base}/Lib',
48 'purelib': '{base}/Lib/site-packages',
49 'platlib': '{base}/Lib/site-packages',
50 'include': '{installed_base}/Include',
51 'platinclude': '{installed_base}/Include',
52 'scripts': '{base}/Scripts',
53 'data': '{base}',
54 },
55 'os2': {
56 'stdlib': '{installed_base}/Lib',
57 'platstdlib': '{base}/Lib',
58 'purelib': '{base}/Lib/site-packages',
59 'platlib': '{base}/Lib/site-packages',
60 'include': '{installed_base}/Include',
61 'platinclude': '{installed_base}/Include',
62 'scripts': '{base}/Scripts',
63 'data': '{base}',
64 },
65 'os2_home': {
66 'stdlib': '{userbase}/lib/python{py_version_short}',
67 'platstdlib': '{userbase}/lib/python{py_version_short}',
68 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
69 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
70 'include': '{userbase}/include/python{py_version_short}',
71 'scripts': '{userbase}/bin',
72 'data': '{userbase}',
73 },
74 'nt_user': {
75 'stdlib': '{userbase}/Python{py_version_nodot}',
76 'platstdlib': '{userbase}/Python{py_version_nodot}',
77 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
78 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
79 'include': '{userbase}/Python{py_version_nodot}/Include',
80 'scripts': '{userbase}/Scripts',
81 'data': '{userbase}',
82 },
83 'posix_user': {
84 'stdlib': '{userbase}/lib/python{py_version_short}',
85 'platstdlib': '{userbase}/lib/python{py_version_short}',
86 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
87 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
88 'include': '{userbase}/include/python{py_version_short}',
89 'scripts': '{userbase}/bin',
90 'data': '{userbase}',
91 },
92 'osx_framework_user': {
93 'stdlib': '{userbase}/lib/python',
94 'platstdlib': '{userbase}/lib/python',
95 'purelib': '{userbase}/lib/python/site-packages',
96 'platlib': '{userbase}/lib/python/site-packages',
97 'include': '{userbase}/include',
98 'scripts': '{userbase}/bin',
99 'data': '{userbase}',
100 },
101 }
Tarek Ziadéedacea32010-01-29 11:41:03 +0000102
Éric Araujoec177c12012-06-24 03:27:43 -0400103_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
104 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200105
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100106 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200107 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +0000108_PY_VERSION = sys.version.split()[0]
109_PY_VERSION_SHORT = sys.version[:3]
110_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
111_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100112_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000113_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100114_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000115_CONFIG_VARS = None
116_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +0000117
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200118
Victor Stinnerb103a932010-10-12 22:23:23 +0000119def _safe_realpath(path):
120 try:
121 return realpath(path)
122 except OSError:
123 return path
124
Victor Stinner171ba052010-03-12 14:20:59 +0000125if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000126 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000127else:
128 # sys.executable can be empty if argv[0] has been changed and Python is
129 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000130 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000131
132if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000133 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000134# PC/VS7.1
135if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000136 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000137# PC/AMD64
138if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000139 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000140
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200141# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200142if "_PYTHON_PROJECT_BASE" in os.environ:
143 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200144
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100145def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000146 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100147 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000148 return True
149 return False
150
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100151_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100152if _sys_home and os.name == 'nt' and \
153 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100154 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100155 if _sys_home.endswith('pcbuild'): # must be amd64
156 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100157def is_python_build(check_home=False):
158 if check_home and _sys_home:
159 return _is_python_source_dir(_sys_home)
160 return _is_python_source_dir(_PROJECT_BASE)
161
162_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000163
164if _PYTHON_BUILD:
165 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400166 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
167 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200169
Éric Araujoec177c12012-06-24 03:27:43 -0400170def _subst_vars(s, local_vars):
171 try:
172 return s.format(**local_vars)
173 except KeyError:
174 try:
175 return s.format(**os.environ)
176 except KeyError as var:
177 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000178
179def _extend_dict(target_dict, other_dict):
180 target_keys = target_dict.keys()
181 for key, value in other_dict.items():
182 if key in target_keys:
183 continue
184 target_dict[key] = value
185
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200186
Tarek Ziadéedacea32010-01-29 11:41:03 +0000187def _expand_vars(scheme, vars):
188 res = {}
189 if vars is None:
190 vars = {}
191 _extend_dict(vars, get_config_vars())
192
Éric Araujoec177c12012-06-24 03:27:43 -0400193 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000194 if os.name in ('posix', 'nt'):
195 value = os.path.expanduser(value)
196 res[key] = os.path.normpath(_subst_vars(value, vars))
197 return res
198
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200199
Tarek Ziadéedacea32010-01-29 11:41:03 +0000200def _get_default_scheme():
201 if os.name == 'posix':
202 # the default scheme for posix is posix_prefix
203 return 'posix_prefix'
204 return os.name
205
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200206
Tarek Ziadéedacea32010-01-29 11:41:03 +0000207def _getuserbase():
208 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200209
Tarek Ziadéedacea32010-01-29 11:41:03 +0000210 def joinuser(*args):
211 return os.path.expanduser(os.path.join(*args))
212
213 # what about 'os2emx', 'riscos' ?
214 if os.name == "nt":
215 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200216 if env_base:
217 return env_base
218 else:
219 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000220
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000221 if sys.platform == "darwin":
222 framework = get_config_var("PYTHONFRAMEWORK")
223 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200224 if env_base:
225 return env_base
226 else:
227 return joinuser("~", "Library", framework, "%d.%d" %
228 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000229
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200230 if env_base:
231 return env_base
232 else:
233 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000234
235
236def _parse_makefile(filename, vars=None):
237 """Parse a Makefile-style file.
238
239 A dictionary containing name/value pairs is returned. If an
240 optional dictionary is passed in as the second argument, it is
241 used instead of a new dictionary.
242 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000243 # Regexes needed for parsing Makefile (and similar syntaxes,
244 # like old-style Setup files).
245 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
246 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
247 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
248
249 if vars is None:
250 vars = {}
251 done = {}
252 notdone = {}
253
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000254 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000255 lines = f.readlines()
256
257 for line in lines:
258 if line.startswith('#') or line.strip() == '':
259 continue
260 m = _variable_rx.match(line)
261 if m:
262 n, v = m.group(1, 2)
263 v = v.strip()
264 # `$$' is a literal `$' in make
265 tmpv = v.replace('$$', '')
266
267 if "$" in tmpv:
268 notdone[n] = v
269 else:
270 try:
271 v = int(v)
272 except ValueError:
273 # insert literal `$'
274 done[n] = v.replace('$$', '$')
275 else:
276 done[n] = v
277
278 # do variable interpolation here
279 variables = list(notdone.keys())
280
Ronald Oussorend21886c2010-07-20 16:07:10 +0000281 # Variables with a 'PY_' prefix in the makefile. These need to
282 # be made available without that prefix through sysconfig.
283 # Special care is needed to ensure that variable expansion works, even
284 # if the expansion uses the name without a prefix.
285 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
286
Tarek Ziadéedacea32010-01-29 11:41:03 +0000287 while len(variables) > 0:
288 for name in tuple(variables):
289 value = notdone[name]
290 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
291 if m is not None:
292 n = m.group(1)
293 found = True
294 if n in done:
295 item = str(done[n])
296 elif n in notdone:
297 # get it on a subsequent round
298 found = False
299 elif n in os.environ:
300 # do it like make: fall back to environment
301 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000302
303 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200304 if (name.startswith('PY_') and
305 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000306 item = ""
307
308 elif 'PY_' + n in notdone:
309 found = False
310
311 else:
312 item = str(done['PY_' + n])
313
Tarek Ziadéedacea32010-01-29 11:41:03 +0000314 else:
315 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000316
Tarek Ziadéedacea32010-01-29 11:41:03 +0000317 if found:
318 after = value[m.end():]
319 value = value[:m.start()] + item + after
320 if "$" in after:
321 notdone[name] = value
322 else:
323 try:
324 value = int(value)
325 except ValueError:
326 done[name] = value.strip()
327 else:
328 done[name] = value
329 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000330
331 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200332 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000333
334 name = name[3:]
335 if name not in done:
336 done[name] = value
337
Tarek Ziadéedacea32010-01-29 11:41:03 +0000338 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200339 # bogus variable reference (e.g. "prefix=$/opt/python");
340 # just drop it since we can't deal
341 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000342 variables.remove(name)
343
Antoine Pitroudbec7802010-10-10 09:37:12 +0000344 # strip spurious spaces
345 for k, v in done.items():
346 if isinstance(v, str):
347 done[k] = v.strip()
348
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349 # save the results in the global dictionary
350 vars.update(done)
351 return vars
352
Tarek Ziadéedacea32010-01-29 11:41:03 +0000353
Barry Warsawebbef6f2010-09-20 15:29:53 +0000354def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000355 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000356 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100357 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200358 if hasattr(sys, 'abiflags'):
359 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
360 else:
361 config_dir_name = 'config'
362 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200364def _generate_posix_vars():
365 """Generate the Python module containing build-time variables."""
366 import pprint
367 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000368 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000369 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000370 try:
371 _parse_makefile(makefile, vars)
372 except IOError as e:
373 msg = "invalid Python installation: unable to open %s" % makefile
374 if hasattr(e, "strerror"):
375 msg = msg + " (%s)" % e.strerror
376 raise IOError(msg)
377 # load the installed pyconfig.h:
378 config_h = get_config_h_filename()
379 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000380 with open(config_h) as f:
381 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000382 except IOError as e:
383 msg = "invalid Python installation: unable to open %s" % config_h
384 if hasattr(e, "strerror"):
385 msg = msg + " (%s)" % e.strerror
386 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000387 # On AIX, there are wrong paths to the linker scripts in the Makefile
388 # -- these paths are relative to the Python source, but when installed
389 # the scripts are in another directory.
390 if _PYTHON_BUILD:
391 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200392
Trent Nelsonee528cc2012-10-17 04:23:50 -0400393 # There's a chicken-and-egg situation on OS X with regards to the
394 # _sysconfigdata module after the changes introduced by #15298:
395 # get_config_vars() is called by get_platform() as part of the
396 # `make pybuilddir.txt` target -- which is a precursor to the
397 # _sysconfigdata.py module being constructed. Unfortunately,
398 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400399 # to import _sysconfigdata, which we won't have built yet. In order
400 # for _init_posix() to work, if we're on Darwin, just mock up the
401 # _sysconfigdata module manually and populate it with the build vars.
402 # This is more than sufficient for ensuring the subsequent call to
403 # get_platform() succeeds.
404 name = '_sysconfigdata'
405 if 'darwin' in sys.platform:
406 import imp
407 module = imp.new_module(name)
408 module.build_time_vars = vars
409 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000410
Trent Nelsonee528cc2012-10-17 04:23:50 -0400411 pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
412 if hasattr(sys, "gettotalrefcount"):
413 pybuilddir += '-pydebug'
414 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400415 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400416
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400417 with open(destfile, 'w', encoding='utf8') as f:
418 f.write('# system configuration generated and used by'
419 ' the sysconfig module\n')
420 f.write('build_time_vars = ')
421 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400422
Trent Nelsonc101bf32012-10-16 08:13:12 -0400423 # Create file used for sys.path fixup -- see Modules/getpath.c
424 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
425 f.write(pybuilddir)
426
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200427def _init_posix(vars):
428 """Initialize the module as appropriate for POSIX systems."""
429 # _sysconfigdata is generated at build time, see _generate_posix_vars()
430 from _sysconfigdata import build_time_vars
431 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200432
Tarek Ziadéedacea32010-01-29 11:41:03 +0000433def _init_non_posix(vars):
434 """Initialize the module as appropriate for NT"""
435 # set basic install directories
436 vars['LIBDEST'] = get_path('stdlib')
437 vars['BINLIBDEST'] = get_path('platstdlib')
438 vars['INCLUDEPY'] = get_path('include')
439 vars['SO'] = '.pyd'
doko@ubuntu.comd5537d02013-03-21 13:21:49 -0700440 vars['EXT_SUFFIX'] = '.pyd'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000441 vars['EXE'] = '.exe'
442 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000443 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000444
445#
446# public APIs
447#
448
Tarek Ziadébd797682010-02-02 23:16:13 +0000449
450def parse_config_h(fp, vars=None):
451 """Parse a config.h-style file.
452
453 A dictionary containing name/value pairs is returned. If an
454 optional dictionary is passed in as the second argument, it is
455 used instead of a new dictionary.
456 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000457 if vars is None:
458 vars = {}
459 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
460 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
461
462 while True:
463 line = fp.readline()
464 if not line:
465 break
466 m = define_rx.match(line)
467 if m:
468 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200469 try:
470 v = int(v)
471 except ValueError:
472 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000473 vars[n] = v
474 else:
475 m = undef_rx.match(line)
476 if m:
477 vars[m.group(1)] = 0
478 return vars
479
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200480
Tarek Ziadébd797682010-02-02 23:16:13 +0000481def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000482 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000483 if _PYTHON_BUILD:
484 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100485 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000486 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100487 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000488 else:
489 inc_dir = get_path('platinclude')
490 return os.path.join(inc_dir, 'pyconfig.h')
491
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200492
Tarek Ziadéedacea32010-01-29 11:41:03 +0000493def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000494 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400495 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200496
Tarek Ziadéedacea32010-01-29 11:41:03 +0000497
498def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000499 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400500 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200501
Tarek Ziadéedacea32010-01-29 11:41:03 +0000502
503def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000504 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000505
506 ``scheme`` is the install scheme name. If not provided, it will
507 return the default scheme for the current platform.
508 """
509 if expand:
510 return _expand_vars(scheme, vars)
511 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400512 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200513
Tarek Ziadéedacea32010-01-29 11:41:03 +0000514
515def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000516 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000517
518 ``scheme`` is the install scheme name.
519 """
520 return get_paths(scheme, vars, expand)[name]
521
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200522
Tarek Ziadéedacea32010-01-29 11:41:03 +0000523def get_config_vars(*args):
524 """With no arguments, return a dictionary of all configuration
525 variables relevant for the current platform.
526
527 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700528 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000529
530 With arguments, return a list of values that result from looking up
531 each argument in the configuration variable dictionary.
532 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000533 global _CONFIG_VARS
534 if _CONFIG_VARS is None:
535 _CONFIG_VARS = {}
536 # Normalized versions of prefix and exec_prefix are handy to have;
537 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400538 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000539 _CONFIG_VARS['prefix'] = _PREFIX
540 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
541 _CONFIG_VARS['py_version'] = _PY_VERSION
542 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
543 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100544 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000545 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100546 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000547 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000548 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000549 try:
550 _CONFIG_VARS['abiflags'] = sys.abiflags
551 except AttributeError:
552 # sys.abiflags may not be defined on all platforms.
553 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000554
555 if os.name in ('nt', 'os2'):
556 _init_non_posix(_CONFIG_VARS)
557 if os.name == 'posix':
558 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000559 # Setting 'userbase' is done below the call to the
560 # init function to enable using 'get_config_var' in
561 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100562 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000563
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100564 # Always convert srcdir to an absolute path
565 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
566 if os.name == 'posix':
567 if _PYTHON_BUILD:
568 # If srcdir is a relative path (typically '.' or '..')
569 # then it should be interpreted relative to the directory
570 # containing Makefile.
571 base = os.path.dirname(get_makefile_filename())
572 srcdir = os.path.join(base, srcdir)
573 else:
574 # srcdir is not meaningful since the installation is
575 # spread about the filesystem. We choose the
576 # directory containing the Makefile since we know it
577 # exists.
578 srcdir = os.path.dirname(get_makefile_filename())
579 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000580
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700581 # OS X platforms require special customization to handle
582 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000583 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700584 import _osx_support
585 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000586
587 if args:
588 vals = []
589 for name in args:
590 vals.append(_CONFIG_VARS.get(name))
591 return vals
592 else:
593 return _CONFIG_VARS
594
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200595
Tarek Ziadéedacea32010-01-29 11:41:03 +0000596def get_config_var(name):
597 """Return the value of a single variable using the dictionary returned by
598 'get_config_vars()'.
599
600 Equivalent to get_config_vars().get(name)
601 """
602 return get_config_vars().get(name)
603
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200604
Tarek Ziadéedacea32010-01-29 11:41:03 +0000605def get_platform():
606 """Return a string that identifies the current platform.
607
608 This is used mainly to distinguish platform-specific build directories and
609 platform-specific built distributions. Typically includes the OS name
610 and version and the architecture (as supplied by 'os.uname()'),
611 although the exact information included depends on the OS; eg. for IRIX
612 the architecture isn't particularly important (IRIX only runs on SGI
613 hardware), but for Linux the kernel version isn't particularly
614 important.
615
616 Examples of returned values:
617 linux-i586
618 linux-alpha (?)
619 solaris-2.6-sun4u
620 irix-5.3
621 irix64-6.2
622
623 Windows will return one of:
624 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
625 win-ia64 (64bit Windows on Itanium)
626 win32 (all others - specifically, sys.platform is returned)
627
628 For other non-POSIX platforms, currently just returns 'sys.platform'.
629 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000630 if os.name == 'nt':
631 # sniff sys.version for architecture.
632 prefix = " bit ("
633 i = sys.version.find(prefix)
634 if i == -1:
635 return sys.platform
636 j = sys.version.find(")", i)
637 look = sys.version[i+len(prefix):j].lower()
638 if look == 'amd64':
639 return 'win-amd64'
640 if look == 'itanium':
641 return 'win-ia64'
642 return sys.platform
643
644 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700645 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000646 return sys.platform
647
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200648 # Set for cross builds explicitly
649 if "_PYTHON_HOST_PLATFORM" in os.environ:
650 return os.environ["_PYTHON_HOST_PLATFORM"]
651
Tarek Ziadéedacea32010-01-29 11:41:03 +0000652 # Try to distinguish various flavours of Unix
653 osname, host, release, version, machine = os.uname()
654
655 # Convert the OS name to lowercase, remove '/' characters
656 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
657 osname = osname.lower().replace('/', '')
658 machine = machine.replace(' ', '_')
659 machine = machine.replace('/', '-')
660
661 if osname[:5] == "linux":
662 # At least on Linux/Intel, 'machine' is the processor --
663 # i386, etc.
664 # XXX what about Alpha, SPARC, etc?
665 return "%s-%s" % (osname, machine)
666 elif osname[:5] == "sunos":
667 if release[0] >= "5": # SunOS 5 == Solaris 2
668 osname = "solaris"
669 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100670 # We can't use "platform.architecture()[0]" because a
671 # bootstrap problem. We use a dict to get an error
672 # if some suspicious happens.
673 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100674 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000675 # fall through to standard osname-release-machine representation
676 elif osname[:4] == "irix": # could be "irix64"!
677 return "%s-%s" % (osname, release)
678 elif osname[:3] == "aix":
679 return "%s-%s.%s" % (osname, version, release)
680 elif osname[:6] == "cygwin":
681 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200682 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000683 m = rel_re.match(release)
684 if m:
685 release = m.group()
686 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700687 import _osx_support
688 osname, release, machine = _osx_support.get_platform_osx(
689 get_config_vars(),
690 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000691
692 return "%s-%s-%s" % (osname, release, machine)
693
694
695def get_python_version():
696 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000697
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200698
Tarek Ziadéa7514992010-05-25 09:44:36 +0000699def _print_dict(title, data):
700 for index, (key, value) in enumerate(sorted(data.items())):
701 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200702 print('%s: ' % (title))
703 print('\t%s = "%s"' % (key, value))
704
Tarek Ziadéa7514992010-05-25 09:44:36 +0000705
706def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000707 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200708 if '--generate-posix-vars' in sys.argv:
709 _generate_posix_vars()
710 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200711 print('Platform: "%s"' % get_platform())
712 print('Python version: "%s"' % get_python_version())
713 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200714 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000715 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200716 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000717 _print_dict('Variables', get_config_vars())
718
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200719
Tarek Ziadéa7514992010-05-25 09:44:36 +0000720if __name__ == '__main__':
721 _main()