blob: e06e82a89f05723624d87d699a7386b49a1a7431 [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 },
Éric Araujoec177c12012-06-24 03:27:43 -040055 'nt_user': {
56 'stdlib': '{userbase}/Python{py_version_nodot}',
57 'platstdlib': '{userbase}/Python{py_version_nodot}',
58 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
59 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
60 'include': '{userbase}/Python{py_version_nodot}/Include',
61 'scripts': '{userbase}/Scripts',
62 'data': '{userbase}',
63 },
64 'posix_user': {
65 'stdlib': '{userbase}/lib/python{py_version_short}',
66 'platstdlib': '{userbase}/lib/python{py_version_short}',
67 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
68 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
69 'include': '{userbase}/include/python{py_version_short}',
70 'scripts': '{userbase}/bin',
71 'data': '{userbase}',
72 },
73 'osx_framework_user': {
74 'stdlib': '{userbase}/lib/python',
75 'platstdlib': '{userbase}/lib/python',
76 'purelib': '{userbase}/lib/python/site-packages',
77 'platlib': '{userbase}/lib/python/site-packages',
78 'include': '{userbase}/include',
79 'scripts': '{userbase}/bin',
80 'data': '{userbase}',
81 },
82 }
Tarek Ziadéedacea32010-01-29 11:41:03 +000083
Éric Araujoec177c12012-06-24 03:27:43 -040084_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
85 'scripts', 'data')
Tarek Ziade1231a4e2011-05-19 13:07:25 +020086
Vinay Sajip7ded1f02012-05-26 03:45:29 +010087 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +020088 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000089_PY_VERSION = sys.version.split()[0]
90_PY_VERSION_SHORT = sys.version[:3]
91_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
92_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010093_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000094_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010095_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000096_CONFIG_VARS = None
97_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000098
Tarek Ziade1231a4e2011-05-19 13:07:25 +020099
Victor Stinnerb103a932010-10-12 22:23:23 +0000100def _safe_realpath(path):
101 try:
102 return realpath(path)
103 except OSError:
104 return path
105
Victor Stinner171ba052010-03-12 14:20:59 +0000106if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +0000107 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +0000108else:
109 # sys.executable can be empty if argv[0] has been changed and Python is
110 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +0000111 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +0000112
113if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000115# PC/VS7.1
116if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000117 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000118# PC/AMD64
119if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +0000120 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000121
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200122# set for cross builds
doko@ubuntu.com7e6c2e22012-06-30 22:35:00 +0200123if "_PYTHON_PROJECT_BASE" in os.environ:
124 _PROJECT_BASE = _safe_realpath(os.environ["_PYTHON_PROJECT_BASE"])
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200125
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100126def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000127 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100128 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000129 return True
130 return False
131
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100132_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100133if _sys_home and os.name == 'nt' and \
134 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100135 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7e203492012-05-27 17:30:09 +0100136 if _sys_home.endswith('pcbuild'): # must be amd64
137 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100138def is_python_build(check_home=False):
139 if check_home and _sys_home:
140 return _is_python_source_dir(_sys_home)
141 return _is_python_source_dir(_PROJECT_BASE)
142
143_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000144
145if _PYTHON_BUILD:
146 for scheme in ('posix_prefix', 'posix_home'):
Éric Araujoec177c12012-06-24 03:27:43 -0400147 _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
148 _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
Tarek Ziadéedacea32010-01-29 11:41:03 +0000149
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200150
Éric Araujoec177c12012-06-24 03:27:43 -0400151def _subst_vars(s, local_vars):
152 try:
153 return s.format(**local_vars)
154 except KeyError:
155 try:
156 return s.format(**os.environ)
157 except KeyError as var:
158 raise AttributeError('{%s}' % var)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000159
160def _extend_dict(target_dict, other_dict):
161 target_keys = target_dict.keys()
162 for key, value in other_dict.items():
163 if key in target_keys:
164 continue
165 target_dict[key] = value
166
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200167
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168def _expand_vars(scheme, vars):
169 res = {}
170 if vars is None:
171 vars = {}
172 _extend_dict(vars, get_config_vars())
173
Éric Araujoec177c12012-06-24 03:27:43 -0400174 for key, value in _INSTALL_SCHEMES[scheme].items():
Tarek Ziadéedacea32010-01-29 11:41:03 +0000175 if os.name in ('posix', 'nt'):
176 value = os.path.expanduser(value)
177 res[key] = os.path.normpath(_subst_vars(value, vars))
178 return res
179
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200180
Tarek Ziadéedacea32010-01-29 11:41:03 +0000181def _get_default_scheme():
182 if os.name == 'posix':
183 # the default scheme for posix is posix_prefix
184 return 'posix_prefix'
185 return os.name
186
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200187
Tarek Ziadéedacea32010-01-29 11:41:03 +0000188def _getuserbase():
189 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200190
Tarek Ziadéedacea32010-01-29 11:41:03 +0000191 def joinuser(*args):
192 return os.path.expanduser(os.path.join(*args))
193
Jesus Cea4791a242012-10-05 03:15:39 +0200194 # what about 'riscos' ?
Tarek Ziadéedacea32010-01-29 11:41:03 +0000195 if os.name == "nt":
196 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200197 if env_base:
198 return env_base
199 else:
200 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000201
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000202 if sys.platform == "darwin":
203 framework = get_config_var("PYTHONFRAMEWORK")
204 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200205 if env_base:
206 return env_base
207 else:
208 return joinuser("~", "Library", framework, "%d.%d" %
209 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000210
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200211 if env_base:
212 return env_base
213 else:
214 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000215
216
217def _parse_makefile(filename, vars=None):
218 """Parse a Makefile-style file.
219
220 A dictionary containing name/value pairs is returned. If an
221 optional dictionary is passed in as the second argument, it is
222 used instead of a new dictionary.
223 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000224 # Regexes needed for parsing Makefile (and similar syntaxes,
225 # like old-style Setup files).
226 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
227 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
228 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
229
230 if vars is None:
231 vars = {}
232 done = {}
233 notdone = {}
234
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000235 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000236 lines = f.readlines()
237
238 for line in lines:
239 if line.startswith('#') or line.strip() == '':
240 continue
241 m = _variable_rx.match(line)
242 if m:
243 n, v = m.group(1, 2)
244 v = v.strip()
245 # `$$' is a literal `$' in make
246 tmpv = v.replace('$$', '')
247
248 if "$" in tmpv:
249 notdone[n] = v
250 else:
251 try:
252 v = int(v)
253 except ValueError:
254 # insert literal `$'
255 done[n] = v.replace('$$', '$')
256 else:
257 done[n] = v
258
259 # do variable interpolation here
260 variables = list(notdone.keys())
261
Ronald Oussorend21886c2010-07-20 16:07:10 +0000262 # Variables with a 'PY_' prefix in the makefile. These need to
263 # be made available without that prefix through sysconfig.
264 # Special care is needed to ensure that variable expansion works, even
265 # if the expansion uses the name without a prefix.
266 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
267
Tarek Ziadéedacea32010-01-29 11:41:03 +0000268 while len(variables) > 0:
269 for name in tuple(variables):
270 value = notdone[name]
271 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
272 if m is not None:
273 n = m.group(1)
274 found = True
275 if n in done:
276 item = str(done[n])
277 elif n in notdone:
278 # get it on a subsequent round
279 found = False
280 elif n in os.environ:
281 # do it like make: fall back to environment
282 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000283
284 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200285 if (name.startswith('PY_') and
286 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000287 item = ""
288
289 elif 'PY_' + n in notdone:
290 found = False
291
292 else:
293 item = str(done['PY_' + n])
294
Tarek Ziadéedacea32010-01-29 11:41:03 +0000295 else:
296 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000297
Tarek Ziadéedacea32010-01-29 11:41:03 +0000298 if found:
299 after = value[m.end():]
300 value = value[:m.start()] + item + after
301 if "$" in after:
302 notdone[name] = value
303 else:
304 try:
305 value = int(value)
306 except ValueError:
307 done[name] = value.strip()
308 else:
309 done[name] = value
310 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000311
312 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200313 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000314
315 name = name[3:]
316 if name not in done:
317 done[name] = value
318
Tarek Ziadéedacea32010-01-29 11:41:03 +0000319 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200320 # bogus variable reference (e.g. "prefix=$/opt/python");
321 # just drop it since we can't deal
322 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000323 variables.remove(name)
324
Antoine Pitroudbec7802010-10-10 09:37:12 +0000325 # strip spurious spaces
326 for k, v in done.items():
327 if isinstance(v, str):
328 done[k] = v.strip()
329
Tarek Ziadéedacea32010-01-29 11:41:03 +0000330 # save the results in the global dictionary
331 vars.update(done)
332 return vars
333
Tarek Ziadéedacea32010-01-29 11:41:03 +0000334
Barry Warsawebbef6f2010-09-20 15:29:53 +0000335def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000336 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000337 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100338 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200339 if hasattr(sys, 'abiflags'):
340 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
341 else:
342 config_dir_name = 'config'
343 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000344
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200345def _generate_posix_vars():
346 """Generate the Python module containing build-time variables."""
347 import pprint
348 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000350 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000351 try:
352 _parse_makefile(makefile, vars)
353 except IOError as e:
354 msg = "invalid Python installation: unable to open %s" % makefile
355 if hasattr(e, "strerror"):
356 msg = msg + " (%s)" % e.strerror
357 raise IOError(msg)
358 # load the installed pyconfig.h:
359 config_h = get_config_h_filename()
360 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000361 with open(config_h) as f:
362 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000363 except IOError as e:
364 msg = "invalid Python installation: unable to open %s" % config_h
365 if hasattr(e, "strerror"):
366 msg = msg + " (%s)" % e.strerror
367 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000368 # On AIX, there are wrong paths to the linker scripts in the Makefile
369 # -- these paths are relative to the Python source, but when installed
370 # the scripts are in another directory.
371 if _PYTHON_BUILD:
372 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200373
Trent Nelsonee528cc2012-10-17 04:23:50 -0400374 # There's a chicken-and-egg situation on OS X with regards to the
375 # _sysconfigdata module after the changes introduced by #15298:
376 # get_config_vars() is called by get_platform() as part of the
377 # `make pybuilddir.txt` target -- which is a precursor to the
378 # _sysconfigdata.py module being constructed. Unfortunately,
379 # get_config_vars() eventually calls _init_posix(), which attempts
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400380 # to import _sysconfigdata, which we won't have built yet. In order
381 # for _init_posix() to work, if we're on Darwin, just mock up the
382 # _sysconfigdata module manually and populate it with the build vars.
383 # This is more than sufficient for ensuring the subsequent call to
384 # get_platform() succeeds.
385 name = '_sysconfigdata'
386 if 'darwin' in sys.platform:
387 import imp
388 module = imp.new_module(name)
389 module.build_time_vars = vars
390 sys.modules[name] = module
Tarek Ziadéedacea32010-01-29 11:41:03 +0000391
Trent Nelsonee528cc2012-10-17 04:23:50 -0400392 pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version[:3])
393 if hasattr(sys, "gettotalrefcount"):
394 pybuilddir += '-pydebug'
395 os.makedirs(pybuilddir, exist_ok=True)
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400396 destfile = os.path.join(pybuilddir, name + '.py')
Trent Nelsonee528cc2012-10-17 04:23:50 -0400397
Trent Nelsonecbe2a92012-10-17 18:03:24 -0400398 with open(destfile, 'w', encoding='utf8') as f:
399 f.write('# system configuration generated and used by'
400 ' the sysconfig module\n')
401 f.write('build_time_vars = ')
402 pprint.pprint(vars, stream=f)
Trent Nelsonee528cc2012-10-17 04:23:50 -0400403
Trent Nelsonc101bf32012-10-16 08:13:12 -0400404 # Create file used for sys.path fixup -- see Modules/getpath.c
405 with open('pybuilddir.txt', 'w', encoding='ascii') as f:
406 f.write(pybuilddir)
407
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200408def _init_posix(vars):
409 """Initialize the module as appropriate for POSIX systems."""
410 # _sysconfigdata is generated at build time, see _generate_posix_vars()
411 from _sysconfigdata import build_time_vars
412 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200413
Tarek Ziadéedacea32010-01-29 11:41:03 +0000414def _init_non_posix(vars):
415 """Initialize the module as appropriate for NT"""
416 # set basic install directories
417 vars['LIBDEST'] = get_path('stdlib')
418 vars['BINLIBDEST'] = get_path('platstdlib')
419 vars['INCLUDEPY'] = get_path('include')
420 vars['SO'] = '.pyd'
421 vars['EXE'] = '.exe'
422 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000423 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000424
425#
426# public APIs
427#
428
Tarek Ziadébd797682010-02-02 23:16:13 +0000429
430def parse_config_h(fp, vars=None):
431 """Parse a config.h-style file.
432
433 A dictionary containing name/value pairs is returned. If an
434 optional dictionary is passed in as the second argument, it is
435 used instead of a new dictionary.
436 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000437 if vars is None:
438 vars = {}
439 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
440 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
441
442 while True:
443 line = fp.readline()
444 if not line:
445 break
446 m = define_rx.match(line)
447 if m:
448 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200449 try:
450 v = int(v)
451 except ValueError:
452 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000453 vars[n] = v
454 else:
455 m = undef_rx.match(line)
456 if m:
457 vars[m.group(1)] = 0
458 return vars
459
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200460
Tarek Ziadébd797682010-02-02 23:16:13 +0000461def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000462 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000463 if _PYTHON_BUILD:
464 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100465 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000466 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100467 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000468 else:
469 inc_dir = get_path('platinclude')
470 return os.path.join(inc_dir, 'pyconfig.h')
471
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200472
Tarek Ziadéedacea32010-01-29 11:41:03 +0000473def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000474 """Return a tuple containing the schemes names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400475 return tuple(sorted(_INSTALL_SCHEMES))
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200476
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477
478def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000479 """Return a tuple containing the paths names."""
Éric Araujoec177c12012-06-24 03:27:43 -0400480 return _SCHEME_KEYS
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200481
Tarek Ziadéedacea32010-01-29 11:41:03 +0000482
483def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000484 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000485
486 ``scheme`` is the install scheme name. If not provided, it will
487 return the default scheme for the current platform.
488 """
489 if expand:
490 return _expand_vars(scheme, vars)
491 else:
Éric Araujoec177c12012-06-24 03:27:43 -0400492 return _INSTALL_SCHEMES[scheme]
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200493
Tarek Ziadéedacea32010-01-29 11:41:03 +0000494
495def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000496 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000497
498 ``scheme`` is the install scheme name.
499 """
500 return get_paths(scheme, vars, expand)[name]
501
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200502
Tarek Ziadéedacea32010-01-29 11:41:03 +0000503def get_config_vars(*args):
504 """With no arguments, return a dictionary of all configuration
505 variables relevant for the current platform.
506
507 On Unix, this means every variable defined in Python's installed Makefile;
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700508 On Windows it's a much smaller set.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000509
510 With arguments, return a list of values that result from looking up
511 each argument in the configuration variable dictionary.
512 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513 global _CONFIG_VARS
514 if _CONFIG_VARS is None:
515 _CONFIG_VARS = {}
516 # Normalized versions of prefix and exec_prefix are handy to have;
517 # in fact, these are the standard versions used most places in the
Éric Araujo859aad62012-06-24 00:07:41 -0400518 # Distutils.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000519 _CONFIG_VARS['prefix'] = _PREFIX
520 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
521 _CONFIG_VARS['py_version'] = _PY_VERSION
522 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
523 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100524 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000525 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100526 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000527 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000528 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000529 try:
530 _CONFIG_VARS['abiflags'] = sys.abiflags
531 except AttributeError:
532 # sys.abiflags may not be defined on all platforms.
533 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000534
Jesus Cea4791a242012-10-05 03:15:39 +0200535 if os.name == 'nt':
Tarek Ziadéedacea32010-01-29 11:41:03 +0000536 _init_non_posix(_CONFIG_VARS)
537 if os.name == 'posix':
538 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000539 # Setting 'userbase' is done below the call to the
540 # init function to enable using 'get_config_var' in
541 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100542 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000543
Richard Oudkerk46874ad2012-07-27 12:06:55 +0100544 # Always convert srcdir to an absolute path
545 srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
546 if os.name == 'posix':
547 if _PYTHON_BUILD:
548 # If srcdir is a relative path (typically '.' or '..')
549 # then it should be interpreted relative to the directory
550 # containing Makefile.
551 base = os.path.dirname(get_makefile_filename())
552 srcdir = os.path.join(base, srcdir)
553 else:
554 # srcdir is not meaningful since the installation is
555 # spread about the filesystem. We choose the
556 # directory containing the Makefile since we know it
557 # exists.
558 srcdir = os.path.dirname(get_makefile_filename())
559 _CONFIG_VARS['srcdir'] = _safe_realpath(srcdir)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000560
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700561 # OS X platforms require special customization to handle
562 # multi-architecture, multi-os-version installers
Tarek Ziadéedacea32010-01-29 11:41:03 +0000563 if sys.platform == 'darwin':
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700564 import _osx_support
565 _osx_support.customize_config_vars(_CONFIG_VARS)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000566
567 if args:
568 vals = []
569 for name in args:
570 vals.append(_CONFIG_VARS.get(name))
571 return vals
572 else:
573 return _CONFIG_VARS
574
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200575
Tarek Ziadéedacea32010-01-29 11:41:03 +0000576def get_config_var(name):
577 """Return the value of a single variable using the dictionary returned by
578 'get_config_vars()'.
579
580 Equivalent to get_config_vars().get(name)
581 """
582 return get_config_vars().get(name)
583
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200584
Tarek Ziadéedacea32010-01-29 11:41:03 +0000585def get_platform():
586 """Return a string that identifies the current platform.
587
588 This is used mainly to distinguish platform-specific build directories and
589 platform-specific built distributions. Typically includes the OS name
590 and version and the architecture (as supplied by 'os.uname()'),
591 although the exact information included depends on the OS; eg. for IRIX
592 the architecture isn't particularly important (IRIX only runs on SGI
593 hardware), but for Linux the kernel version isn't particularly
594 important.
595
596 Examples of returned values:
597 linux-i586
598 linux-alpha (?)
599 solaris-2.6-sun4u
600 irix-5.3
601 irix64-6.2
602
603 Windows will return one of:
604 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
605 win-ia64 (64bit Windows on Itanium)
606 win32 (all others - specifically, sys.platform is returned)
607
608 For other non-POSIX platforms, currently just returns 'sys.platform'.
609 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000610 if os.name == 'nt':
611 # sniff sys.version for architecture.
612 prefix = " bit ("
613 i = sys.version.find(prefix)
614 if i == -1:
615 return sys.platform
616 j = sys.version.find(")", i)
617 look = sys.version[i+len(prefix):j].lower()
618 if look == 'amd64':
619 return 'win-amd64'
620 if look == 'itanium':
621 return 'win-ia64'
622 return sys.platform
623
624 if os.name != "posix" or not hasattr(os, 'uname'):
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700625 # XXX what about the architecture? NT is Intel or Alpha
Tarek Ziadéedacea32010-01-29 11:41:03 +0000626 return sys.platform
627
doko@ubuntu.com1abe1c52012-06-30 20:42:45 +0200628 # Set for cross builds explicitly
629 if "_PYTHON_HOST_PLATFORM" in os.environ:
630 return os.environ["_PYTHON_HOST_PLATFORM"]
631
Tarek Ziadéedacea32010-01-29 11:41:03 +0000632 # Try to distinguish various flavours of Unix
633 osname, host, release, version, machine = os.uname()
634
635 # Convert the OS name to lowercase, remove '/' characters
636 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
637 osname = osname.lower().replace('/', '')
638 machine = machine.replace(' ', '_')
639 machine = machine.replace('/', '-')
640
641 if osname[:5] == "linux":
642 # At least on Linux/Intel, 'machine' is the processor --
643 # i386, etc.
644 # XXX what about Alpha, SPARC, etc?
645 return "%s-%s" % (osname, machine)
646 elif osname[:5] == "sunos":
647 if release[0] >= "5": # SunOS 5 == Solaris 2
648 osname = "solaris"
649 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100650 # We can't use "platform.architecture()[0]" because a
651 # bootstrap problem. We use a dict to get an error
652 # if some suspicious happens.
653 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100654 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000655 # fall through to standard osname-release-machine representation
656 elif osname[:4] == "irix": # could be "irix64"!
657 return "%s-%s" % (osname, release)
658 elif osname[:3] == "aix":
659 return "%s-%s.%s" % (osname, version, release)
660 elif osname[:6] == "cygwin":
661 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200662 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000663 m = rel_re.match(release)
664 if m:
665 release = m.group()
666 elif osname[:6] == "darwin":
Ned Deilydf8aa2b2012-07-21 05:36:30 -0700667 import _osx_support
668 osname, release, machine = _osx_support.get_platform_osx(
669 get_config_vars(),
670 osname, release, machine)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000671
672 return "%s-%s-%s" % (osname, release, machine)
673
674
675def get_python_version():
676 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000677
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200678
Tarek Ziadéa7514992010-05-25 09:44:36 +0000679def _print_dict(title, data):
680 for index, (key, value) in enumerate(sorted(data.items())):
681 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200682 print('%s: ' % (title))
683 print('\t%s = "%s"' % (key, value))
684
Tarek Ziadéa7514992010-05-25 09:44:36 +0000685
686def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000687 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200688 if '--generate-posix-vars' in sys.argv:
689 _generate_posix_vars()
690 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200691 print('Platform: "%s"' % get_platform())
692 print('Python version: "%s"' % get_python_version())
693 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200694 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000695 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200696 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000697 _print_dict('Variables', get_config_vars())
698
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200699
Tarek Ziadéa7514992010-05-25 09:44:36 +0000700if __name__ == '__main__':
701 _main()