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