blob: eccd3041a4e1ca75730bc1997ee009a71ced586b [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
142if "_PROJECT_BASE" in os.environ:
143 _PROJECT_BASE = _safe_realpath(os.environ["_PROJECT_BASE"])
144
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
393 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200394 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200395 f.write('# system configuration generated and used by'
396 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200397 f.write('build_time_vars = ')
398 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000399
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200400def _init_posix(vars):
401 """Initialize the module as appropriate for POSIX systems."""
402 # _sysconfigdata is generated at build time, see _generate_posix_vars()
403 from _sysconfigdata import build_time_vars
404 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200405
Tarek Ziadéedacea32010-01-29 11:41:03 +0000406def _init_non_posix(vars):
407 """Initialize the module as appropriate for NT"""
408 # set basic install directories
409 vars['LIBDEST'] = get_path('stdlib')
410 vars['BINLIBDEST'] = get_path('platstdlib')
411 vars['INCLUDEPY'] = get_path('include')
412 vars['SO'] = '.pyd'
413 vars['EXE'] = '.exe'
414 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000415 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000416
417#
418# public APIs
419#
420
Tarek Ziadébd797682010-02-02 23:16:13 +0000421
422def parse_config_h(fp, vars=None):
423 """Parse a config.h-style file.
424
425 A dictionary containing name/value pairs is returned. If an
426 optional dictionary is passed in as the second argument, it is
427 used instead of a new dictionary.
428 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000429 if vars is None:
430 vars = {}
431 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
432 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
433
434 while True:
435 line = fp.readline()
436 if not line:
437 break
438 m = define_rx.match(line)
439 if m:
440 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200441 try:
442 v = int(v)
443 except ValueError:
444 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000445 vars[n] = v
446 else:
447 m = undef_rx.match(line)
448 if m:
449 vars[m.group(1)] = 0
450 return vars
451
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200452
Tarek Ziadébd797682010-02-02 23:16:13 +0000453def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000454 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000455 if _PYTHON_BUILD:
456 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100457 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000458 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100459 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000460 else:
461 inc_dir = get_path('platinclude')
462 return os.path.join(inc_dir, 'pyconfig.h')
463
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200464
Tarek Ziadéedacea32010-01-29 11:41:03 +0000465def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000466 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400467 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200468
Tarek Ziadéedacea32010-01-29 11:41:03 +0000469
470def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000471 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400472 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200473
Tarek Ziadéedacea32010-01-29 11:41:03 +0000474
475def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000476 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477
478 ``scheme`` is the install scheme name. If not provided, it will
479 return the default scheme for the current platform.
480 """
481 if expand:
482 return _expand_vars(scheme, vars)
483 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400484 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200485
Tarek Ziadéedacea32010-01-29 11:41:03 +0000486
487def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000488 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489
490 ``scheme`` is the install scheme name.
491 """
492 return get_paths(scheme, vars, expand)[name]
493
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200494
Tarek Ziadéedacea32010-01-29 11:41:03 +0000495def get_config_vars(*args):
496 """With no arguments, return a dictionary of all configuration
497 variables relevant for the current platform.
498
499 On Unix, this means every variable defined in Python's installed Makefile;
500 On Windows and Mac OS it's a much smaller set.
501
502 With arguments, return a list of values that result from looking up
503 each argument in the configuration variable dictionary.
504 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000505 global _CONFIG_VARS
506 if _CONFIG_VARS is None:
507 _CONFIG_VARS = {}
508 # Normalized versions of prefix and exec_prefix are handy to have;
509 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400510 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000511 _CONFIG_VARS['prefix'] = _PREFIX
512 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
513 _CONFIG_VARS['py_version'] = _PY_VERSION
514 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
515 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100516 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000517 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100518 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000519 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000520 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000521 try:
522 _CONFIG_VARS['abiflags'] = sys.abiflags
523 except AttributeError:
524 # sys.abiflags may not be defined on all platforms.
525 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000526
527 if os.name in ('nt', 'os2'):
528 _init_non_posix(_CONFIG_VARS)
529 if os.name == 'posix':
530 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000531 # Setting 'userbase' is done below the call to the
532 # init function to enable using 'get_config_var' in
533 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100534 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000535
Tarek Ziadéedacea32010-01-29 11:41:03 +0000536 if 'srcdir' not in _CONFIG_VARS:
537 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000538 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000539 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000540
Tarek Ziadéedacea32010-01-29 11:41:03 +0000541 # Convert srcdir into an absolute path if it appears necessary.
542 # Normally it is relative to the build directory. However, during
543 # testing, for example, we might be running a non-installed python
544 # from a different directory.
545 if _PYTHON_BUILD and os.name == "posix":
546 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000547 try:
548 cwd = os.getcwd()
549 except OSError:
550 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000551 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000552 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000553 # srcdir is relative and we are not in the same directory
554 # as the executable. Assume executable is in the build
555 # directory and make srcdir absolute.
556 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
557 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
558
559 if sys.platform == 'darwin':
Larry Hastings68386bc2012-06-24 14:30:41 -0700560 kernel_version = os.uname().release # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000561 major_version = int(kernel_version.split('.')[0])
562
563 if major_version < 8:
564 # On Mac OS X before 10.4, check if -arch and -isysroot
565 # are in CFLAGS or LDFLAGS and remove them if they are.
566 # This is needed when building extensions on a 10.3 system
567 # using a universal build of python.
568 for key in ('LDFLAGS', 'BASECFLAGS',
569 # a number of derived variables. These need to be
570 # patched up as well.
571 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
572 flags = _CONFIG_VARS[key]
573 flags = re.sub('-arch\s+\w+\s', ' ', flags)
574 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
575 _CONFIG_VARS[key] = flags
576 else:
577 # Allow the user to override the architecture flags using
578 # an environment variable.
579 # NOTE: This name was introduced by Apple in OSX 10.5 and
580 # is used by several scripting languages distributed with
581 # that OS release.
582 if 'ARCHFLAGS' in os.environ:
583 arch = os.environ['ARCHFLAGS']
584 for key in ('LDFLAGS', 'BASECFLAGS',
585 # a number of derived variables. These need to be
586 # patched up as well.
587 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
588
589 flags = _CONFIG_VARS[key]
590 flags = re.sub('-arch\s+\w+\s', ' ', flags)
591 flags = flags + ' ' + arch
592 _CONFIG_VARS[key] = flags
593
594 # If we're on OSX 10.5 or later and the user tries to
595 # compiles an extension using an SDK that is not present
596 # on the current machine it is better to not use an SDK
597 # than to fail.
598 #
599 # The major usecase for this is users using a Python.org
600 # binary installer on OSX 10.6: that installer uses
601 # the 10.4u SDK, but that SDK is not installed by default
602 # when you install Xcode.
603 #
604 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
605 m = re.search('-isysroot\s+(\S+)', CFLAGS)
606 if m is not None:
607 sdk = m.group(1)
608 if not os.path.exists(sdk):
609 for key in ('LDFLAGS', 'BASECFLAGS',
610 # a number of derived variables. These need to be
611 # patched up as well.
612 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
613
614 flags = _CONFIG_VARS[key]
615 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
616 _CONFIG_VARS[key] = flags
617
618 if args:
619 vals = []
620 for name in args:
621 vals.append(_CONFIG_VARS.get(name))
622 return vals
623 else:
624 return _CONFIG_VARS
625
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200626
Tarek Ziadéedacea32010-01-29 11:41:03 +0000627def get_config_var(name):
628 """Return the value of a single variable using the dictionary returned by
629 'get_config_vars()'.
630
631 Equivalent to get_config_vars().get(name)
632 """
633 return get_config_vars().get(name)
634
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200635
Tarek Ziadéedacea32010-01-29 11:41:03 +0000636def get_platform():
637 """Return a string that identifies the current platform.
638
639 This is used mainly to distinguish platform-specific build directories and
640 platform-specific built distributions. Typically includes the OS name
641 and version and the architecture (as supplied by 'os.uname()'),
642 although the exact information included depends on the OS; eg. for IRIX
643 the architecture isn't particularly important (IRIX only runs on SGI
644 hardware), but for Linux the kernel version isn't particularly
645 important.
646
647 Examples of returned values:
648 linux-i586
649 linux-alpha (?)
650 solaris-2.6-sun4u
651 irix-5.3
652 irix64-6.2
653
654 Windows will return one of:
655 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
656 win-ia64 (64bit Windows on Itanium)
657 win32 (all others - specifically, sys.platform is returned)
658
659 For other non-POSIX platforms, currently just returns 'sys.platform'.
660 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000661 if os.name == 'nt':
662 # sniff sys.version for architecture.
663 prefix = " bit ("
664 i = sys.version.find(prefix)
665 if i == -1:
666 return sys.platform
667 j = sys.version.find(")", i)
668 look = sys.version[i+len(prefix):j].lower()
669 if look == 'amd64':
670 return 'win-amd64'
671 if look == 'itanium':
672 return 'win-ia64'
673 return sys.platform
674
675 if os.name != "posix" or not hasattr(os, 'uname'):
676 # XXX what about the architecture? NT is Intel or Alpha,
677 # Mac OS is M68k or PPC, etc.
678 return sys.platform
679
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200680 # Set for cross builds explicitly
681 if "_PYTHON_HOST_PLATFORM" in os.environ:
682 return os.environ["_PYTHON_HOST_PLATFORM"]
683
Tarek Ziadéedacea32010-01-29 11:41:03 +0000684 # Try to distinguish various flavours of Unix
685 osname, host, release, version, machine = os.uname()
686
687 # Convert the OS name to lowercase, remove '/' characters
688 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
689 osname = osname.lower().replace('/', '')
690 machine = machine.replace(' ', '_')
691 machine = machine.replace('/', '-')
692
693 if osname[:5] == "linux":
694 # At least on Linux/Intel, 'machine' is the processor --
695 # i386, etc.
696 # XXX what about Alpha, SPARC, etc?
697 return "%s-%s" % (osname, machine)
698 elif osname[:5] == "sunos":
699 if release[0] >= "5": # SunOS 5 == Solaris 2
700 osname = "solaris"
701 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100702 # We can't use "platform.architecture()[0]" because a
703 # bootstrap problem. We use a dict to get an error
704 # if some suspicious happens.
705 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100706 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000707 # fall through to standard osname-release-machine representation
708 elif osname[:4] == "irix": # could be "irix64"!
709 return "%s-%s" % (osname, release)
710 elif osname[:3] == "aix":
711 return "%s-%s.%s" % (osname, version, release)
712 elif osname[:6] == "cygwin":
713 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200714 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000715 m = rel_re.match(release)
716 if m:
717 release = m.group()
718 elif osname[:6] == "darwin":
719 #
720 # For our purposes, we'll assume that the system version from
721 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
722 # to. This makes the compatibility story a bit more sane because the
723 # machine is going to compile and link as if it were
724 # MACOSX_DEPLOYMENT_TARGET.
725 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200726 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000727
Éric Araujo559b5f12011-05-25 18:21:43 +0200728 if True:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000729 # Always calculate the release of the running machine,
730 # needed to determine if we can build fat binaries or not.
731
732 macrelease = macver
733 # Get the system version. Reading this plist is a documented
734 # way to get the system version (see the documentation for
735 # the Gestalt Manager)
736 try:
737 f = open('/System/Library/CoreServices/SystemVersion.plist')
738 except IOError:
739 # We're on a plain darwin box, fall back to the default
740 # behaviour.
741 pass
742 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000743 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200744 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
745 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000746 finally:
747 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200748 if m is not None:
749 macrelease = '.'.join(m.group(1).split('.')[:2])
750 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000751
752 if not macver:
753 macver = macrelease
754
755 if macver:
756 release = macver
757 osname = "macosx"
758
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200759 if ((macrelease + '.') >= '10.4.' and
760 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000761 # The universal build will build fat binaries, but not on
762 # systems before 10.4
763 #
764 # Try to detect 4-way universal builds, those have machine-type
765 # 'universal' instead of 'fat'.
766
767 machine = 'fat'
768 cflags = get_config_vars().get('CFLAGS')
769
770 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000771 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000772
773 if len(archs) == 1:
774 machine = archs[0]
775 elif archs == ('i386', 'ppc'):
776 machine = 'fat'
777 elif archs == ('i386', 'x86_64'):
778 machine = 'intel'
779 elif archs == ('i386', 'ppc', 'x86_64'):
780 machine = 'fat3'
781 elif archs == ('ppc64', 'x86_64'):
782 machine = 'fat64'
783 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
784 machine = 'universal'
785 else:
786 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200787 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000788
789 elif machine == 'i386':
790 # On OSX the machine type returned by uname is always the
791 # 32-bit variant, even if the executable architecture is
792 # the 64-bit variant
793 if sys.maxsize >= 2**32:
794 machine = 'x86_64'
795
796 elif machine in ('PowerPC', 'Power_Macintosh'):
797 # Pick a sane name for the PPC architecture.
798 # See 'i386' case
799 if sys.maxsize >= 2**32:
800 machine = 'ppc64'
801 else:
802 machine = 'ppc'
803
804 return "%s-%s-%s" % (osname, release, machine)
805
806
807def get_python_version():
808 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000809
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200810
Tarek Ziadéa7514992010-05-25 09:44:36 +0000811def _print_dict(title, data):
812 for index, (key, value) in enumerate(sorted(data.items())):
813 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200814 print('%s: ' % (title))
815 print('\t%s = "%s"' % (key, value))
816
Tarek Ziadéa7514992010-05-25 09:44:36 +0000817
818def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000819 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200820 if '--generate-posix-vars' in sys.argv:
821 _generate_posix_vars()
822 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200823 print('Platform: "%s"' % get_platform())
824 print('Python version: "%s"' % get_python_version())
825 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200826 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000827 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200828 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000829 _print_dict('Variables', get_config_vars())
830
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200831
Tarek Ziadéa7514992010-05-25 09:44:36 +0000832if __name__ == '__main__':
833 _main()