blob: 2f5d9d0c9cd230add1dbcd0ea67999441b36f674 [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
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100141def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000142 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100143 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000144 return True
145 return False
146
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100147_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100148if _sys_home and os.name == 'nt' and \
149 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100150 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100151 if _sys_home.endswith('pcbuild'): # must be amd64
152 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100153def is_python_build(check_home=False):
154 if check_home and _sys_home:
155 return _is_python_source_dir(_sys_home)
156 return _is_python_source_dir(_PROJECT_BASE)
157
158_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000159
160if _PYTHON_BUILD:
161 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400162 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
163 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000164
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200165
Éric Araujoec177c12012-06-24 03:27:43 -0400166def _subst_vars(s, local_vars):
167 try:
168 return s.format(**local_vars)
169 except KeyError:
170 try:
171 return s.format(**os.environ)
172 except KeyError as var:
173 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000174
175def _extend_dict(target_dict, other_dict):
176 target_keys = target_dict.keys()
177 for key, value in other_dict.items():
178 if key in target_keys:
179 continue
180 target_dict[key] = value
181
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200182
Tarek Ziadéedacea32010-01-29 11:41:03 +0000183def _expand_vars(scheme, vars):
184 res = {}
185 if vars is None:
186 vars = {}
187 _extend_dict(vars, get_config_vars())
188
Éric Araujoec177c12012-06-24 03:27:43 -0400189 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000190 if os.name in ('posix', 'nt'):
191 value = os.path.expanduser(value)
192 res[key] = os.path.normpath(_subst_vars(value, vars))
193 return res
194
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200195
Tarek Ziadéedacea32010-01-29 11:41:03 +0000196def _get_default_scheme():
197 if os.name == 'posix':
198 # the default scheme for posix is posix_prefix
199 return 'posix_prefix'
200 return os.name
201
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200202
Tarek Ziadéedacea32010-01-29 11:41:03 +0000203def _getuserbase():
204 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200205
Tarek Ziadéedacea32010-01-29 11:41:03 +0000206 def joinuser(*args):
207 return os.path.expanduser(os.path.join(*args))
208
209 # what about 'os2emx', 'riscos' ?
210 if os.name == "nt":
211 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200212 if env_base:
213 return env_base
214 else:
215 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000216
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000217 if sys.platform == "darwin":
218 framework = get_config_var("PYTHONFRAMEWORK")
219 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200220 if env_base:
221 return env_base
222 else:
223 return joinuser("~", "Library", framework, "%d.%d" %
224 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000225
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200226 if env_base:
227 return env_base
228 else:
229 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000230
231
232def _parse_makefile(filename, vars=None):
233 """Parse a Makefile-style file.
234
235 A dictionary containing name/value pairs is returned. If an
236 optional dictionary is passed in as the second argument, it is
237 used instead of a new dictionary.
238 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000239 # Regexes needed for parsing Makefile (and similar syntaxes,
240 # like old-style Setup files).
241 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
242 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
243 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
244
245 if vars is None:
246 vars = {}
247 done = {}
248 notdone = {}
249
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000250 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000251 lines = f.readlines()
252
253 for line in lines:
254 if line.startswith('#') or line.strip() == '':
255 continue
256 m = _variable_rx.match(line)
257 if m:
258 n, v = m.group(1, 2)
259 v = v.strip()
260 # `$$' is a literal `$' in make
261 tmpv = v.replace('$$', '')
262
263 if "$" in tmpv:
264 notdone[n] = v
265 else:
266 try:
267 v = int(v)
268 except ValueError:
269 # insert literal `$'
270 done[n] = v.replace('$$', '$')
271 else:
272 done[n] = v
273
274 # do variable interpolation here
275 variables = list(notdone.keys())
276
Ronald Oussorend21886c2010-07-20 16:07:10 +0000277 # Variables with a 'PY_' prefix in the makefile. These need to
278 # be made available without that prefix through sysconfig.
279 # Special care is needed to ensure that variable expansion works, even
280 # if the expansion uses the name without a prefix.
281 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
282
Tarek Ziadéedacea32010-01-29 11:41:03 +0000283 while len(variables) > 0:
284 for name in tuple(variables):
285 value = notdone[name]
286 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
287 if m is not None:
288 n = m.group(1)
289 found = True
290 if n in done:
291 item = str(done[n])
292 elif n in notdone:
293 # get it on a subsequent round
294 found = False
295 elif n in os.environ:
296 # do it like make: fall back to environment
297 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000298
299 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200300 if (name.startswith('PY_') and
301 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000302 item = ""
303
304 elif 'PY_' + n in notdone:
305 found = False
306
307 else:
308 item = str(done['PY_' + n])
309
Tarek Ziadéedacea32010-01-29 11:41:03 +0000310 else:
311 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000312
Tarek Ziadéedacea32010-01-29 11:41:03 +0000313 if found:
314 after = value[m.end():]
315 value = value[:m.start()] + item + after
316 if "$" in after:
317 notdone[name] = value
318 else:
319 try:
320 value = int(value)
321 except ValueError:
322 done[name] = value.strip()
323 else:
324 done[name] = value
325 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000326
327 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200328 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000329
330 name = name[3:]
331 if name not in done:
332 done[name] = value
333
Tarek Ziadéedacea32010-01-29 11:41:03 +0000334 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200335 # bogus variable reference (e.g. "prefix=$/opt/python");
336 # just drop it since we can't deal
337 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000338 variables.remove(name)
339
Antoine Pitroudbec7802010-10-10 09:37:12 +0000340 # strip spurious spaces
341 for k, v in done.items():
342 if isinstance(v, str):
343 done[k] = v.strip()
344
Tarek Ziadéedacea32010-01-29 11:41:03 +0000345 # save the results in the global dictionary
346 vars.update(done)
347 return vars
348
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349
Barry Warsawebbef6f2010-09-20 15:29:53 +0000350def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000351 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000352 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100353 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200354 if hasattr(sys, 'abiflags'):
355 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
356 else:
357 config_dir_name = 'config'
358 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000359
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200360def _generate_posix_vars():
361 """Generate the Python module containing build-time variables."""
362 import pprint
363 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000364 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000365 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000366 try:
367 _parse_makefile(makefile, vars)
368 except IOError as e:
369 msg = "invalid Python installation: unable to open %s" % makefile
370 if hasattr(e, "strerror"):
371 msg = msg + " (%s)" % e.strerror
372 raise IOError(msg)
373 # load the installed pyconfig.h:
374 config_h = get_config_h_filename()
375 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000376 with open(config_h) as f:
377 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000378 except IOError as e:
379 msg = "invalid Python installation: unable to open %s" % config_h
380 if hasattr(e, "strerror"):
381 msg = msg + " (%s)" % e.strerror
382 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000383 # On AIX, there are wrong paths to the linker scripts in the Makefile
384 # -- these paths are relative to the Python source, but when installed
385 # the scripts are in another directory.
386 if _PYTHON_BUILD:
387 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200388
389 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200390 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200391 f.write('# system configuration generated and used by'
392 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200393 f.write('build_time_vars = ')
394 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000395
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200396def _init_posix(vars):
397 """Initialize the module as appropriate for POSIX systems."""
398 # _sysconfigdata is generated at build time, see _generate_posix_vars()
399 from _sysconfigdata import build_time_vars
400 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200401
Tarek Ziadéedacea32010-01-29 11:41:03 +0000402def _init_non_posix(vars):
403 """Initialize the module as appropriate for NT"""
404 # set basic install directories
405 vars['LIBDEST'] = get_path('stdlib')
406 vars['BINLIBDEST'] = get_path('platstdlib')
407 vars['INCLUDEPY'] = get_path('include')
408 vars['SO'] = '.pyd'
409 vars['EXE'] = '.exe'
410 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000411 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000412
413#
414# public APIs
415#
416
Tarek Ziadébd797682010-02-02 23:16:13 +0000417
418def parse_config_h(fp, vars=None):
419 """Parse a config.h-style file.
420
421 A dictionary containing name/value pairs is returned. If an
422 optional dictionary is passed in as the second argument, it is
423 used instead of a new dictionary.
424 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000425 if vars is None:
426 vars = {}
427 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
428 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
429
430 while True:
431 line = fp.readline()
432 if not line:
433 break
434 m = define_rx.match(line)
435 if m:
436 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200437 try:
438 v = int(v)
439 except ValueError:
440 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000441 vars[n] = v
442 else:
443 m = undef_rx.match(line)
444 if m:
445 vars[m.group(1)] = 0
446 return vars
447
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200448
Tarek Ziadébd797682010-02-02 23:16:13 +0000449def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000450 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000451 if _PYTHON_BUILD:
452 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100453 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000454 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100455 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000456 else:
457 inc_dir = get_path('platinclude')
458 return os.path.join(inc_dir, 'pyconfig.h')
459
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200460
Tarek Ziadéedacea32010-01-29 11:41:03 +0000461def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000462 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400463 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200464
Tarek Ziadéedacea32010-01-29 11:41:03 +0000465
466def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000467 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400468 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200469
Tarek Ziadéedacea32010-01-29 11:41:03 +0000470
471def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000472 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000473
474 ``scheme`` is the install scheme name. If not provided, it will
475 return the default scheme for the current platform.
476 """
477 if expand:
478 return _expand_vars(scheme, vars)
479 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400480 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200481
Tarek Ziadéedacea32010-01-29 11:41:03 +0000482
483def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000484 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000485
486 ``scheme`` is the install scheme name.
487 """
488 return get_paths(scheme, vars, expand)[name]
489
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200490
Tarek Ziadéedacea32010-01-29 11:41:03 +0000491def get_config_vars(*args):
492 """With no arguments, return a dictionary of all configuration
493 variables relevant for the current platform.
494
495 On Unix, this means every variable defined in Python's installed Makefile;
496 On Windows and Mac OS it's a much smaller set.
497
498 With arguments, return a list of values that result from looking up
499 each argument in the configuration variable dictionary.
500 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000501 global _CONFIG_VARS
502 if _CONFIG_VARS is None:
503 _CONFIG_VARS = {}
504 # Normalized versions of prefix and exec_prefix are handy to have;
505 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400506 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000507 _CONFIG_VARS['prefix'] = _PREFIX
508 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
509 _CONFIG_VARS['py_version'] = _PY_VERSION
510 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
511 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100512 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100514 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000515 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000516 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000517 try:
518 _CONFIG_VARS['abiflags'] = sys.abiflags
519 except AttributeError:
520 # sys.abiflags may not be defined on all platforms.
521 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000522
523 if os.name in ('nt', 'os2'):
524 _init_non_posix(_CONFIG_VARS)
525 if os.name == 'posix':
526 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000527 # Setting 'userbase' is done below the call to the
528 # init function to enable using 'get_config_var' in
529 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100530 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000531
Tarek Ziadéedacea32010-01-29 11:41:03 +0000532 if 'srcdir' not in _CONFIG_VARS:
533 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000534 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000535 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000536
Tarek Ziadéedacea32010-01-29 11:41:03 +0000537 # Convert srcdir into an absolute path if it appears necessary.
538 # Normally it is relative to the build directory. However, during
539 # testing, for example, we might be running a non-installed python
540 # from a different directory.
541 if _PYTHON_BUILD and os.name == "posix":
542 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000543 try:
544 cwd = os.getcwd()
545 except OSError:
546 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000547 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000548 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000549 # srcdir is relative and we are not in the same directory
550 # as the executable. Assume executable is in the build
551 # directory and make srcdir absolute.
552 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
553 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
554
555 if sys.platform == 'darwin':
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200556 kernel_version = os.uname()[2] # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000557 major_version = int(kernel_version.split('.')[0])
558
559 if major_version < 8:
560 # On Mac OS X before 10.4, check if -arch and -isysroot
561 # are in CFLAGS or LDFLAGS and remove them if they are.
562 # This is needed when building extensions on a 10.3 system
563 # using a universal build of python.
564 for key in ('LDFLAGS', 'BASECFLAGS',
565 # a number of derived variables. These need to be
566 # patched up as well.
567 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
568 flags = _CONFIG_VARS[key]
569 flags = re.sub('-arch\s+\w+\s', ' ', flags)
570 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
571 _CONFIG_VARS[key] = flags
572 else:
573 # Allow the user to override the architecture flags using
574 # an environment variable.
575 # NOTE: This name was introduced by Apple in OSX 10.5 and
576 # is used by several scripting languages distributed with
577 # that OS release.
578 if 'ARCHFLAGS' in os.environ:
579 arch = os.environ['ARCHFLAGS']
580 for key in ('LDFLAGS', 'BASECFLAGS',
581 # a number of derived variables. These need to be
582 # patched up as well.
583 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
584
585 flags = _CONFIG_VARS[key]
586 flags = re.sub('-arch\s+\w+\s', ' ', flags)
587 flags = flags + ' ' + arch
588 _CONFIG_VARS[key] = flags
589
590 # If we're on OSX 10.5 or later and the user tries to
591 # compiles an extension using an SDK that is not present
592 # on the current machine it is better to not use an SDK
593 # than to fail.
594 #
595 # The major usecase for this is users using a Python.org
596 # binary installer on OSX 10.6: that installer uses
597 # the 10.4u SDK, but that SDK is not installed by default
598 # when you install Xcode.
599 #
600 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
601 m = re.search('-isysroot\s+(\S+)', CFLAGS)
602 if m is not None:
603 sdk = m.group(1)
604 if not os.path.exists(sdk):
605 for key in ('LDFLAGS', 'BASECFLAGS',
606 # a number of derived variables. These need to be
607 # patched up as well.
608 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
609
610 flags = _CONFIG_VARS[key]
611 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
612 _CONFIG_VARS[key] = flags
613
614 if args:
615 vals = []
616 for name in args:
617 vals.append(_CONFIG_VARS.get(name))
618 return vals
619 else:
620 return _CONFIG_VARS
621
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200622
Tarek Ziadéedacea32010-01-29 11:41:03 +0000623def get_config_var(name):
624 """Return the value of a single variable using the dictionary returned by
625 'get_config_vars()'.
626
627 Equivalent to get_config_vars().get(name)
628 """
629 return get_config_vars().get(name)
630
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200631
Tarek Ziadéedacea32010-01-29 11:41:03 +0000632def get_platform():
633 """Return a string that identifies the current platform.
634
635 This is used mainly to distinguish platform-specific build directories and
636 platform-specific built distributions. Typically includes the OS name
637 and version and the architecture (as supplied by 'os.uname()'),
638 although the exact information included depends on the OS; eg. for IRIX
639 the architecture isn't particularly important (IRIX only runs on SGI
640 hardware), but for Linux the kernel version isn't particularly
641 important.
642
643 Examples of returned values:
644 linux-i586
645 linux-alpha (?)
646 solaris-2.6-sun4u
647 irix-5.3
648 irix64-6.2
649
650 Windows will return one of:
651 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
652 win-ia64 (64bit Windows on Itanium)
653 win32 (all others - specifically, sys.platform is returned)
654
655 For other non-POSIX platforms, currently just returns 'sys.platform'.
656 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000657 if os.name == 'nt':
658 # sniff sys.version for architecture.
659 prefix = " bit ("
660 i = sys.version.find(prefix)
661 if i == -1:
662 return sys.platform
663 j = sys.version.find(")", i)
664 look = sys.version[i+len(prefix):j].lower()
665 if look == 'amd64':
666 return 'win-amd64'
667 if look == 'itanium':
668 return 'win-ia64'
669 return sys.platform
670
671 if os.name != "posix" or not hasattr(os, 'uname'):
672 # XXX what about the architecture? NT is Intel or Alpha,
673 # Mac OS is M68k or PPC, etc.
674 return sys.platform
675
676 # Try to distinguish various flavours of Unix
677 osname, host, release, version, machine = os.uname()
678
679 # Convert the OS name to lowercase, remove '/' characters
680 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
681 osname = osname.lower().replace('/', '')
682 machine = machine.replace(' ', '_')
683 machine = machine.replace('/', '-')
684
685 if osname[:5] == "linux":
686 # At least on Linux/Intel, 'machine' is the processor --
687 # i386, etc.
688 # XXX what about Alpha, SPARC, etc?
689 return "%s-%s" % (osname, machine)
690 elif osname[:5] == "sunos":
691 if release[0] >= "5": # SunOS 5 == Solaris 2
692 osname = "solaris"
693 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100694 # We can't use "platform.architecture()[0]" because a
695 # bootstrap problem. We use a dict to get an error
696 # if some suspicious happens.
697 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100698 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000699 # fall through to standard osname-release-machine representation
700 elif osname[:4] == "irix": # could be "irix64"!
701 return "%s-%s" % (osname, release)
702 elif osname[:3] == "aix":
703 return "%s-%s.%s" % (osname, version, release)
704 elif osname[:6] == "cygwin":
705 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200706 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000707 m = rel_re.match(release)
708 if m:
709 release = m.group()
710 elif osname[:6] == "darwin":
711 #
712 # For our purposes, we'll assume that the system version from
713 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
714 # to. This makes the compatibility story a bit more sane because the
715 # machine is going to compile and link as if it were
716 # MACOSX_DEPLOYMENT_TARGET.
717 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200718 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000719
Éric Araujo559b5f12011-05-25 18:21:43 +0200720 if True:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000721 # Always calculate the release of the running machine,
722 # needed to determine if we can build fat binaries or not.
723
724 macrelease = macver
725 # Get the system version. Reading this plist is a documented
726 # way to get the system version (see the documentation for
727 # the Gestalt Manager)
728 try:
729 f = open('/System/Library/CoreServices/SystemVersion.plist')
730 except IOError:
731 # We're on a plain darwin box, fall back to the default
732 # behaviour.
733 pass
734 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000735 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200736 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
737 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000738 finally:
739 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200740 if m is not None:
741 macrelease = '.'.join(m.group(1).split('.')[:2])
742 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000743
744 if not macver:
745 macver = macrelease
746
747 if macver:
748 release = macver
749 osname = "macosx"
750
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200751 if ((macrelease + '.') >= '10.4.' and
752 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000753 # The universal build will build fat binaries, but not on
754 # systems before 10.4
755 #
756 # Try to detect 4-way universal builds, those have machine-type
757 # 'universal' instead of 'fat'.
758
759 machine = 'fat'
760 cflags = get_config_vars().get('CFLAGS')
761
762 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000763 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000764
765 if len(archs) == 1:
766 machine = archs[0]
767 elif archs == ('i386', 'ppc'):
768 machine = 'fat'
769 elif archs == ('i386', 'x86_64'):
770 machine = 'intel'
771 elif archs == ('i386', 'ppc', 'x86_64'):
772 machine = 'fat3'
773 elif archs == ('ppc64', 'x86_64'):
774 machine = 'fat64'
775 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
776 machine = 'universal'
777 else:
778 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200779 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000780
781 elif machine == 'i386':
782 # On OSX the machine type returned by uname is always the
783 # 32-bit variant, even if the executable architecture is
784 # the 64-bit variant
785 if sys.maxsize >= 2**32:
786 machine = 'x86_64'
787
788 elif machine in ('PowerPC', 'Power_Macintosh'):
789 # Pick a sane name for the PPC architecture.
790 # See 'i386' case
791 if sys.maxsize >= 2**32:
792 machine = 'ppc64'
793 else:
794 machine = 'ppc'
795
796 return "%s-%s-%s" % (osname, release, machine)
797
798
799def get_python_version():
800 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000801
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200802
Tarek Ziadéa7514992010-05-25 09:44:36 +0000803def _print_dict(title, data):
804 for index, (key, value) in enumerate(sorted(data.items())):
805 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200806 print('%s: ' % (title))
807 print('\t%s = "%s"' % (key, value))
808
Tarek Ziadéa7514992010-05-25 09:44:36 +0000809
810def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000811 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200812 if '--generate-posix-vars' in sys.argv:
813 _generate_posix_vars()
814 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200815 print('Platform: "%s"' % get_platform())
816 print('Python version: "%s"' % get_python_version())
817 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200818 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000819 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200820 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000821 _print_dict('Variables', get_config_vars())
822
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200823
Tarek Ziadéa7514992010-05-25 09:44:36 +0000824if __name__ == '__main__':
825 _main()