blob: 7350efbfa04aaed2bbac397f1206148e9e0d2996 [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
Vinay Sajip7ded1f02012-05-26 03:45:29 +01006import os
Florent Xiclunaa4707382010-03-11 00:05:17 +00007from os.path import pardir, realpath
Tarek Ziade1231a4e2011-05-19 13:07:25 +02008from configparser import RawConfigParser
Tarek Ziadéedacea32010-01-29 11:41:03 +00009
Barry Warsawebbef6f2010-09-20 15:29:53 +000010__all__ = [
11 'get_config_h_filename',
12 'get_config_var',
13 'get_config_vars',
14 'get_makefile_filename',
15 'get_path',
16 'get_path_names',
17 'get_paths',
18 'get_platform',
19 'get_python_version',
20 'get_scheme_names',
21 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020022]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000023
Tarek Ziade1231a4e2011-05-19 13:07:25 +020024# let's read the configuration file
25# XXX _CONFIG_DIR will be set by the Makefile later
26_CONFIG_DIR = os.path.normpath(os.path.dirname(__file__))
27_CONFIG_FILE = os.path.join(_CONFIG_DIR, 'sysconfig.cfg')
Antoine Pitroudc567e42011-10-11 16:07:30 +020028_SCHEMES = RawConfigParser(dict_type=dict) # Faster than OrderedDict
Tarek Ziade1231a4e2011-05-19 13:07:25 +020029_SCHEMES.read(_CONFIG_FILE)
30_VAR_REPL = re.compile(r'\{([^{]*?)\}')
Tarek Ziadéedacea32010-01-29 11:41:03 +000031
Tarek Ziade1231a4e2011-05-19 13:07:25 +020032
33def _expand_globals(config):
34 if config.has_section('globals'):
35 globals = config.items('globals')
36 else:
37 globals = tuple()
38
39 sections = config.sections()
40 for section in sections:
41 if section == 'globals':
42 continue
43 for option, value in globals:
44 if config.has_option(section, option):
45 continue
46 config.set(section, option, value)
47 config.remove_section('globals')
48
49 # now expanding local variables defined in the cfg file
50 #
51 for section in config.sections():
52 variables = dict(config.items(section))
53
54 def _replacer(matchobj):
55 name = matchobj.group(1)
56 if name in variables:
57 return variables[name]
58 return matchobj.group(0)
59
60 for option, value in config.items(section):
61 config.set(section, option, _VAR_REPL.sub(_replacer, value))
62
63_expand_globals(_SCHEMES)
64
Vinay Sajip7ded1f02012-05-26 03:45:29 +010065 # FIXME don't rely on sys.version here, its format is an implementation detail
Tarek Ziade1231a4e2011-05-19 13:07:25 +020066 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000067_PY_VERSION = sys.version.split()[0]
68_PY_VERSION_SHORT = sys.version[:3]
69_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
70_PREFIX = os.path.normpath(sys.prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010071_BASE_PREFIX = os.path.normpath(sys.base_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000072_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
Vinay Sajip7ded1f02012-05-26 03:45:29 +010073_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
Tarek Ziadéedacea32010-01-29 11:41:03 +000074_CONFIG_VARS = None
75_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000076
Tarek Ziade1231a4e2011-05-19 13:07:25 +020077
Victor Stinnerb103a932010-10-12 22:23:23 +000078def _safe_realpath(path):
79 try:
80 return realpath(path)
81 except OSError:
82 return path
83
Victor Stinner171ba052010-03-12 14:20:59 +000084if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +000085 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +000086else:
87 # sys.executable can be empty if argv[0] has been changed and Python is
88 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +000089 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +000090
91if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +000092 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +000093# PC/VS7.1
94if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +000095 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +000096# PC/AMD64
97if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +000098 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +000099
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100100def _is_python_source_dir(d):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000101 for fn in ("Setup.dist", "Setup.local"):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100102 if os.path.isfile(os.path.join(d, "Modules", fn)):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000103 return True
104 return False
105
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100106_sys_home = getattr(sys, '_home', None)
Vinay Sajip42211422012-05-26 20:36:12 +0100107if _sys_home and os.name == 'nt' and \
108 _sys_home.lower().endswith(('pcbuild', 'pcbuild\\amd64')):
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100109 _sys_home = os.path.dirname(_sys_home)
110
111def is_python_build(check_home=False):
112 if check_home and _sys_home:
113 return _is_python_source_dir(_sys_home)
114 return _is_python_source_dir(_PROJECT_BASE)
115
116_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000117
118if _PYTHON_BUILD:
119 for scheme in ('posix_prefix', 'posix_home'):
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200120 _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
121 _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000122
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200123
124def _subst_vars(path, local_vars):
125 """In the string `path`, replace tokens like {some.thing} with the
126 corresponding value from the map `local_vars`.
127
128 If there is no corresponding value, leave the token unchanged.
129 """
130 def _replacer(matchobj):
131 name = matchobj.group(1)
132 if name in local_vars:
133 return local_vars[name]
134 elif name in os.environ:
135 return os.environ[name]
136 return matchobj.group(0)
137 return _VAR_REPL.sub(_replacer, path)
138
Tarek Ziadéedacea32010-01-29 11:41:03 +0000139
140def _extend_dict(target_dict, other_dict):
141 target_keys = target_dict.keys()
142 for key, value in other_dict.items():
143 if key in target_keys:
144 continue
145 target_dict[key] = value
146
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200147
Tarek Ziadéedacea32010-01-29 11:41:03 +0000148def _expand_vars(scheme, vars):
149 res = {}
150 if vars is None:
151 vars = {}
152 _extend_dict(vars, get_config_vars())
153
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200154 for key, value in _SCHEMES.items(scheme):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000155 if os.name in ('posix', 'nt'):
156 value = os.path.expanduser(value)
157 res[key] = os.path.normpath(_subst_vars(value, vars))
158 return res
159
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200160
161def format_value(value, vars):
162 def _replacer(matchobj):
163 name = matchobj.group(1)
164 if name in vars:
165 return vars[name]
166 return matchobj.group(0)
167 return _VAR_REPL.sub(_replacer, value)
168
169
Tarek Ziadéedacea32010-01-29 11:41:03 +0000170def _get_default_scheme():
171 if os.name == 'posix':
172 # the default scheme for posix is posix_prefix
173 return 'posix_prefix'
174 return os.name
175
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200176
Tarek Ziadéedacea32010-01-29 11:41:03 +0000177def _getuserbase():
178 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200179
Tarek Ziadéedacea32010-01-29 11:41:03 +0000180 def joinuser(*args):
181 return os.path.expanduser(os.path.join(*args))
182
183 # what about 'os2emx', 'riscos' ?
184 if os.name == "nt":
185 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200186 if env_base:
187 return env_base
188 else:
189 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000190
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000191 if sys.platform == "darwin":
192 framework = get_config_var("PYTHONFRAMEWORK")
193 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200194 if env_base:
195 return env_base
196 else:
197 return joinuser("~", "Library", framework, "%d.%d" %
198 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000199
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200200 if env_base:
201 return env_base
202 else:
203 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000204
205
206def _parse_makefile(filename, vars=None):
207 """Parse a Makefile-style file.
208
209 A dictionary containing name/value pairs is returned. If an
210 optional dictionary is passed in as the second argument, it is
211 used instead of a new dictionary.
212 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000213 # Regexes needed for parsing Makefile (and similar syntaxes,
214 # like old-style Setup files).
215 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
216 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
217 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
218
219 if vars is None:
220 vars = {}
221 done = {}
222 notdone = {}
223
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000224 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000225 lines = f.readlines()
226
227 for line in lines:
228 if line.startswith('#') or line.strip() == '':
229 continue
230 m = _variable_rx.match(line)
231 if m:
232 n, v = m.group(1, 2)
233 v = v.strip()
234 # `$$' is a literal `$' in make
235 tmpv = v.replace('$$', '')
236
237 if "$" in tmpv:
238 notdone[n] = v
239 else:
240 try:
241 v = int(v)
242 except ValueError:
243 # insert literal `$'
244 done[n] = v.replace('$$', '$')
245 else:
246 done[n] = v
247
248 # do variable interpolation here
249 variables = list(notdone.keys())
250
Ronald Oussorend21886c2010-07-20 16:07:10 +0000251 # Variables with a 'PY_' prefix in the makefile. These need to
252 # be made available without that prefix through sysconfig.
253 # Special care is needed to ensure that variable expansion works, even
254 # if the expansion uses the name without a prefix.
255 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
256
Tarek Ziadéedacea32010-01-29 11:41:03 +0000257 while len(variables) > 0:
258 for name in tuple(variables):
259 value = notdone[name]
260 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
261 if m is not None:
262 n = m.group(1)
263 found = True
264 if n in done:
265 item = str(done[n])
266 elif n in notdone:
267 # get it on a subsequent round
268 found = False
269 elif n in os.environ:
270 # do it like make: fall back to environment
271 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000272
273 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200274 if (name.startswith('PY_') and
275 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000276 item = ""
277
278 elif 'PY_' + n in notdone:
279 found = False
280
281 else:
282 item = str(done['PY_' + n])
283
Tarek Ziadéedacea32010-01-29 11:41:03 +0000284 else:
285 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000286
Tarek Ziadéedacea32010-01-29 11:41:03 +0000287 if found:
288 after = value[m.end():]
289 value = value[:m.start()] + item + after
290 if "$" in after:
291 notdone[name] = value
292 else:
293 try:
294 value = int(value)
295 except ValueError:
296 done[name] = value.strip()
297 else:
298 done[name] = value
299 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000300
301 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200302 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000303
304 name = name[3:]
305 if name not in done:
306 done[name] = value
307
Tarek Ziadéedacea32010-01-29 11:41:03 +0000308 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200309 # bogus variable reference (e.g. "prefix=$/opt/python");
310 # just drop it since we can't deal
311 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000312 variables.remove(name)
313
Antoine Pitroudbec7802010-10-10 09:37:12 +0000314 # strip spurious spaces
315 for k, v in done.items():
316 if isinstance(v, str):
317 done[k] = v.strip()
318
Tarek Ziadéedacea32010-01-29 11:41:03 +0000319 # save the results in the global dictionary
320 vars.update(done)
321 return vars
322
Tarek Ziadéedacea32010-01-29 11:41:03 +0000323
Barry Warsawebbef6f2010-09-20 15:29:53 +0000324def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000325 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000326 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100327 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200328 if hasattr(sys, 'abiflags'):
329 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
330 else:
331 config_dir_name = 'config'
332 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000333
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200334def _generate_posix_vars():
335 """Generate the Python module containing build-time variables."""
336 import pprint
337 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000338 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000339 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000340 try:
341 _parse_makefile(makefile, vars)
342 except IOError as e:
343 msg = "invalid Python installation: unable to open %s" % makefile
344 if hasattr(e, "strerror"):
345 msg = msg + " (%s)" % e.strerror
346 raise IOError(msg)
347 # load the installed pyconfig.h:
348 config_h = get_config_h_filename()
349 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000350 with open(config_h) as f:
351 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000352 except IOError as e:
353 msg = "invalid Python installation: unable to open %s" % config_h
354 if hasattr(e, "strerror"):
355 msg = msg + " (%s)" % e.strerror
356 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000357 # On AIX, there are wrong paths to the linker scripts in the Makefile
358 # -- these paths are relative to the Python source, but when installed
359 # the scripts are in another directory.
360 if _PYTHON_BUILD:
361 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200362
363 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200364 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200365 f.write('# system configuration generated and used by'
366 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200367 f.write('build_time_vars = ')
368 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000369
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200370def _init_posix(vars):
371 """Initialize the module as appropriate for POSIX systems."""
372 # _sysconfigdata is generated at build time, see _generate_posix_vars()
373 from _sysconfigdata import build_time_vars
374 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200375
Tarek Ziadéedacea32010-01-29 11:41:03 +0000376def _init_non_posix(vars):
377 """Initialize the module as appropriate for NT"""
378 # set basic install directories
379 vars['LIBDEST'] = get_path('stdlib')
380 vars['BINLIBDEST'] = get_path('platstdlib')
381 vars['INCLUDEPY'] = get_path('include')
382 vars['SO'] = '.pyd'
383 vars['EXE'] = '.exe'
384 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000385 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000386
387#
388# public APIs
389#
390
Tarek Ziadébd797682010-02-02 23:16:13 +0000391
392def parse_config_h(fp, vars=None):
393 """Parse a config.h-style file.
394
395 A dictionary containing name/value pairs is returned. If an
396 optional dictionary is passed in as the second argument, it is
397 used instead of a new dictionary.
398 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000399 if vars is None:
400 vars = {}
401 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
402 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
403
404 while True:
405 line = fp.readline()
406 if not line:
407 break
408 m = define_rx.match(line)
409 if m:
410 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200411 try:
412 v = int(v)
413 except ValueError:
414 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000415 vars[n] = v
416 else:
417 m = undef_rx.match(line)
418 if m:
419 vars[m.group(1)] = 0
420 return vars
421
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200422
Tarek Ziadébd797682010-02-02 23:16:13 +0000423def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000424 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000425 if _PYTHON_BUILD:
426 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100427 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000428 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100429 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000430 else:
431 inc_dir = get_path('platinclude')
432 return os.path.join(inc_dir, 'pyconfig.h')
433
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200434
Tarek Ziadéedacea32010-01-29 11:41:03 +0000435def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000436 """Return a tuple containing the schemes names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200437 return tuple(sorted(_SCHEMES.sections()))
438
Tarek Ziadéedacea32010-01-29 11:41:03 +0000439
440def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000441 """Return a tuple containing the paths names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200442 # xxx see if we want a static list
443 return _SCHEMES.options('posix_prefix')
444
Tarek Ziadéedacea32010-01-29 11:41:03 +0000445
446def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000447 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000448
449 ``scheme`` is the install scheme name. If not provided, it will
450 return the default scheme for the current platform.
451 """
452 if expand:
453 return _expand_vars(scheme, vars)
454 else:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200455 return dict(_SCHEMES.items(scheme))
456
Tarek Ziadéedacea32010-01-29 11:41:03 +0000457
458def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000459 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000460
461 ``scheme`` is the install scheme name.
462 """
463 return get_paths(scheme, vars, expand)[name]
464
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200465
Tarek Ziadéedacea32010-01-29 11:41:03 +0000466def get_config_vars(*args):
467 """With no arguments, return a dictionary of all configuration
468 variables relevant for the current platform.
469
470 On Unix, this means every variable defined in Python's installed Makefile;
471 On Windows and Mac OS it's a much smaller set.
472
473 With arguments, return a list of values that result from looking up
474 each argument in the configuration variable dictionary.
475 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000476 global _CONFIG_VARS
477 if _CONFIG_VARS is None:
478 _CONFIG_VARS = {}
479 # Normalized versions of prefix and exec_prefix are handy to have;
480 # in fact, these are the standard versions used most places in the
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200481 # packaging module.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000482 _CONFIG_VARS['prefix'] = _PREFIX
483 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
484 _CONFIG_VARS['py_version'] = _PY_VERSION
485 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
486 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100487 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000488 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100489 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000490 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000491 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000492 try:
493 _CONFIG_VARS['abiflags'] = sys.abiflags
494 except AttributeError:
495 # sys.abiflags may not be defined on all platforms.
496 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000497
498 if os.name in ('nt', 'os2'):
499 _init_non_posix(_CONFIG_VARS)
500 if os.name == 'posix':
501 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000502 # Setting 'userbase' is done below the call to the
503 # init function to enable using 'get_config_var' in
504 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100505 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000506
Tarek Ziadéedacea32010-01-29 11:41:03 +0000507 if 'srcdir' not in _CONFIG_VARS:
508 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000509 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000510 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000511
Tarek Ziadéedacea32010-01-29 11:41:03 +0000512 # Convert srcdir into an absolute path if it appears necessary.
513 # Normally it is relative to the build directory. However, during
514 # testing, for example, we might be running a non-installed python
515 # from a different directory.
516 if _PYTHON_BUILD and os.name == "posix":
517 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000518 try:
519 cwd = os.getcwd()
520 except OSError:
521 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000522 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000523 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000524 # srcdir is relative and we are not in the same directory
525 # as the executable. Assume executable is in the build
526 # directory and make srcdir absolute.
527 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
528 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
529
530 if sys.platform == 'darwin':
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200531 kernel_version = os.uname()[2] # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000532 major_version = int(kernel_version.split('.')[0])
533
534 if major_version < 8:
535 # On Mac OS X before 10.4, check if -arch and -isysroot
536 # are in CFLAGS or LDFLAGS and remove them if they are.
537 # This is needed when building extensions on a 10.3 system
538 # using a universal build of python.
539 for key in ('LDFLAGS', 'BASECFLAGS',
540 # a number of derived variables. These need to be
541 # patched up as well.
542 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
543 flags = _CONFIG_VARS[key]
544 flags = re.sub('-arch\s+\w+\s', ' ', flags)
545 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
546 _CONFIG_VARS[key] = flags
547 else:
548 # Allow the user to override the architecture flags using
549 # an environment variable.
550 # NOTE: This name was introduced by Apple in OSX 10.5 and
551 # is used by several scripting languages distributed with
552 # that OS release.
553 if 'ARCHFLAGS' in os.environ:
554 arch = os.environ['ARCHFLAGS']
555 for key in ('LDFLAGS', 'BASECFLAGS',
556 # a number of derived variables. These need to be
557 # patched up as well.
558 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
559
560 flags = _CONFIG_VARS[key]
561 flags = re.sub('-arch\s+\w+\s', ' ', flags)
562 flags = flags + ' ' + arch
563 _CONFIG_VARS[key] = flags
564
565 # If we're on OSX 10.5 or later and the user tries to
566 # compiles an extension using an SDK that is not present
567 # on the current machine it is better to not use an SDK
568 # than to fail.
569 #
570 # The major usecase for this is users using a Python.org
571 # binary installer on OSX 10.6: that installer uses
572 # the 10.4u SDK, but that SDK is not installed by default
573 # when you install Xcode.
574 #
575 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
576 m = re.search('-isysroot\s+(\S+)', CFLAGS)
577 if m is not None:
578 sdk = m.group(1)
579 if not os.path.exists(sdk):
580 for key in ('LDFLAGS', 'BASECFLAGS',
581 # a number of derived variables. These need to be
582 # patched up as well.
583 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
584
585 flags = _CONFIG_VARS[key]
586 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
587 _CONFIG_VARS[key] = flags
588
589 if args:
590 vals = []
591 for name in args:
592 vals.append(_CONFIG_VARS.get(name))
593 return vals
594 else:
595 return _CONFIG_VARS
596
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200597
Tarek Ziadéedacea32010-01-29 11:41:03 +0000598def get_config_var(name):
599 """Return the value of a single variable using the dictionary returned by
600 'get_config_vars()'.
601
602 Equivalent to get_config_vars().get(name)
603 """
604 return get_config_vars().get(name)
605
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200606
Tarek Ziadéedacea32010-01-29 11:41:03 +0000607def get_platform():
608 """Return a string that identifies the current platform.
609
610 This is used mainly to distinguish platform-specific build directories and
611 platform-specific built distributions. Typically includes the OS name
612 and version and the architecture (as supplied by 'os.uname()'),
613 although the exact information included depends on the OS; eg. for IRIX
614 the architecture isn't particularly important (IRIX only runs on SGI
615 hardware), but for Linux the kernel version isn't particularly
616 important.
617
618 Examples of returned values:
619 linux-i586
620 linux-alpha (?)
621 solaris-2.6-sun4u
622 irix-5.3
623 irix64-6.2
624
625 Windows will return one of:
626 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
627 win-ia64 (64bit Windows on Itanium)
628 win32 (all others - specifically, sys.platform is returned)
629
630 For other non-POSIX platforms, currently just returns 'sys.platform'.
631 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000632 if os.name == 'nt':
633 # sniff sys.version for architecture.
634 prefix = " bit ("
635 i = sys.version.find(prefix)
636 if i == -1:
637 return sys.platform
638 j = sys.version.find(")", i)
639 look = sys.version[i+len(prefix):j].lower()
640 if look == 'amd64':
641 return 'win-amd64'
642 if look == 'itanium':
643 return 'win-ia64'
644 return sys.platform
645
646 if os.name != "posix" or not hasattr(os, 'uname'):
647 # XXX what about the architecture? NT is Intel or Alpha,
648 # Mac OS is M68k or PPC, etc.
649 return sys.platform
650
651 # 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":
686 #
687 # For our purposes, we'll assume that the system version from
688 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
689 # to. This makes the compatibility story a bit more sane because the
690 # machine is going to compile and link as if it were
691 # MACOSX_DEPLOYMENT_TARGET.
692 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200693 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000694
Éric Araujo559b5f12011-05-25 18:21:43 +0200695 if True:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000696 # Always calculate the release of the running machine,
697 # needed to determine if we can build fat binaries or not.
698
699 macrelease = macver
700 # Get the system version. Reading this plist is a documented
701 # way to get the system version (see the documentation for
702 # the Gestalt Manager)
703 try:
704 f = open('/System/Library/CoreServices/SystemVersion.plist')
705 except IOError:
706 # We're on a plain darwin box, fall back to the default
707 # behaviour.
708 pass
709 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000710 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200711 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
712 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000713 finally:
714 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200715 if m is not None:
716 macrelease = '.'.join(m.group(1).split('.')[:2])
717 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000718
719 if not macver:
720 macver = macrelease
721
722 if macver:
723 release = macver
724 osname = "macosx"
725
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200726 if ((macrelease + '.') >= '10.4.' and
727 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000728 # The universal build will build fat binaries, but not on
729 # systems before 10.4
730 #
731 # Try to detect 4-way universal builds, those have machine-type
732 # 'universal' instead of 'fat'.
733
734 machine = 'fat'
735 cflags = get_config_vars().get('CFLAGS')
736
737 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000738 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000739
740 if len(archs) == 1:
741 machine = archs[0]
742 elif archs == ('i386', 'ppc'):
743 machine = 'fat'
744 elif archs == ('i386', 'x86_64'):
745 machine = 'intel'
746 elif archs == ('i386', 'ppc', 'x86_64'):
747 machine = 'fat3'
748 elif archs == ('ppc64', 'x86_64'):
749 machine = 'fat64'
750 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
751 machine = 'universal'
752 else:
753 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200754 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000755
756 elif machine == 'i386':
757 # On OSX the machine type returned by uname is always the
758 # 32-bit variant, even if the executable architecture is
759 # the 64-bit variant
760 if sys.maxsize >= 2**32:
761 machine = 'x86_64'
762
763 elif machine in ('PowerPC', 'Power_Macintosh'):
764 # Pick a sane name for the PPC architecture.
765 # See 'i386' case
766 if sys.maxsize >= 2**32:
767 machine = 'ppc64'
768 else:
769 machine = 'ppc'
770
771 return "%s-%s-%s" % (osname, release, machine)
772
773
774def get_python_version():
775 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000776
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200777
Tarek Ziadéa7514992010-05-25 09:44:36 +0000778def _print_dict(title, data):
779 for index, (key, value) in enumerate(sorted(data.items())):
780 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200781 print('%s: ' % (title))
782 print('\t%s = "%s"' % (key, value))
783
Tarek Ziadéa7514992010-05-25 09:44:36 +0000784
785def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000786 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200787 if '--generate-posix-vars' in sys.argv:
788 _generate_posix_vars()
789 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200790 print('Platform: "%s"' % get_platform())
791 print('Python version: "%s"' % get_python_version())
792 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200793 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000794 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200795 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000796 _print_dict('Variables', get_config_vars())
797
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200798
Tarek Ziadéa7514992010-05-25 09:44:36 +0000799if __name__ == '__main__':
800 _main()