blob: ac1e75107c436665a17858112f37fef947a72d1a [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)
Vinay Sajip7e203492012-05-27 17:30:09 +0100110 if _sys_home.endswith('pcbuild'): # must be amd64
111 _sys_home = os.path.dirname(_sys_home)
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100112def is_python_build(check_home=False):
113 if check_home and _sys_home:
114 return _is_python_source_dir(_sys_home)
115 return _is_python_source_dir(_PROJECT_BASE)
116
117_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000118
119if _PYTHON_BUILD:
120 for scheme in ('posix_prefix', 'posix_home'):
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200121 _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
122 _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000123
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200124
125def _subst_vars(path, local_vars):
126 """In the string `path`, replace tokens like {some.thing} with the
127 corresponding value from the map `local_vars`.
128
129 If there is no corresponding value, leave the token unchanged.
130 """
131 def _replacer(matchobj):
132 name = matchobj.group(1)
133 if name in local_vars:
134 return local_vars[name]
135 elif name in os.environ:
136 return os.environ[name]
137 return matchobj.group(0)
138 return _VAR_REPL.sub(_replacer, path)
139
Tarek Ziadéedacea32010-01-29 11:41:03 +0000140
141def _extend_dict(target_dict, other_dict):
142 target_keys = target_dict.keys()
143 for key, value in other_dict.items():
144 if key in target_keys:
145 continue
146 target_dict[key] = value
147
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200148
Tarek Ziadéedacea32010-01-29 11:41:03 +0000149def _expand_vars(scheme, vars):
150 res = {}
151 if vars is None:
152 vars = {}
153 _extend_dict(vars, get_config_vars())
154
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200155 for key, value in _SCHEMES.items(scheme):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000156 if os.name in ('posix', 'nt'):
157 value = os.path.expanduser(value)
158 res[key] = os.path.normpath(_subst_vars(value, vars))
159 return res
160
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200161
162def format_value(value, vars):
163 def _replacer(matchobj):
164 name = matchobj.group(1)
165 if name in vars:
166 return vars[name]
167 return matchobj.group(0)
168 return _VAR_REPL.sub(_replacer, value)
169
170
Tarek Ziadéedacea32010-01-29 11:41:03 +0000171def _get_default_scheme():
172 if os.name == 'posix':
173 # the default scheme for posix is posix_prefix
174 return 'posix_prefix'
175 return os.name
176
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200177
Tarek Ziadéedacea32010-01-29 11:41:03 +0000178def _getuserbase():
179 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200180
Tarek Ziadéedacea32010-01-29 11:41:03 +0000181 def joinuser(*args):
182 return os.path.expanduser(os.path.join(*args))
183
184 # what about 'os2emx', 'riscos' ?
185 if os.name == "nt":
186 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200187 if env_base:
188 return env_base
189 else:
190 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000191
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000192 if sys.platform == "darwin":
193 framework = get_config_var("PYTHONFRAMEWORK")
194 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200195 if env_base:
196 return env_base
197 else:
198 return joinuser("~", "Library", framework, "%d.%d" %
199 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000200
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200201 if env_base:
202 return env_base
203 else:
204 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000205
206
207def _parse_makefile(filename, vars=None):
208 """Parse a Makefile-style file.
209
210 A dictionary containing name/value pairs is returned. If an
211 optional dictionary is passed in as the second argument, it is
212 used instead of a new dictionary.
213 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000214 # Regexes needed for parsing Makefile (and similar syntaxes,
215 # like old-style Setup files).
216 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
217 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
218 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
219
220 if vars is None:
221 vars = {}
222 done = {}
223 notdone = {}
224
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000225 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000226 lines = f.readlines()
227
228 for line in lines:
229 if line.startswith('#') or line.strip() == '':
230 continue
231 m = _variable_rx.match(line)
232 if m:
233 n, v = m.group(1, 2)
234 v = v.strip()
235 # `$$' is a literal `$' in make
236 tmpv = v.replace('$$', '')
237
238 if "$" in tmpv:
239 notdone[n] = v
240 else:
241 try:
242 v = int(v)
243 except ValueError:
244 # insert literal `$'
245 done[n] = v.replace('$$', '$')
246 else:
247 done[n] = v
248
249 # do variable interpolation here
250 variables = list(notdone.keys())
251
Ronald Oussorend21886c2010-07-20 16:07:10 +0000252 # Variables with a 'PY_' prefix in the makefile. These need to
253 # be made available without that prefix through sysconfig.
254 # Special care is needed to ensure that variable expansion works, even
255 # if the expansion uses the name without a prefix.
256 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
257
Tarek Ziadéedacea32010-01-29 11:41:03 +0000258 while len(variables) > 0:
259 for name in tuple(variables):
260 value = notdone[name]
261 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
262 if m is not None:
263 n = m.group(1)
264 found = True
265 if n in done:
266 item = str(done[n])
267 elif n in notdone:
268 # get it on a subsequent round
269 found = False
270 elif n in os.environ:
271 # do it like make: fall back to environment
272 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000273
274 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200275 if (name.startswith('PY_') and
276 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000277 item = ""
278
279 elif 'PY_' + n in notdone:
280 found = False
281
282 else:
283 item = str(done['PY_' + n])
284
Tarek Ziadéedacea32010-01-29 11:41:03 +0000285 else:
286 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000287
Tarek Ziadéedacea32010-01-29 11:41:03 +0000288 if found:
289 after = value[m.end():]
290 value = value[:m.start()] + item + after
291 if "$" in after:
292 notdone[name] = value
293 else:
294 try:
295 value = int(value)
296 except ValueError:
297 done[name] = value.strip()
298 else:
299 done[name] = value
300 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000301
302 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200303 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000304
305 name = name[3:]
306 if name not in done:
307 done[name] = value
308
Tarek Ziadéedacea32010-01-29 11:41:03 +0000309 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200310 # bogus variable reference (e.g. "prefix=$/opt/python");
311 # just drop it since we can't deal
312 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000313 variables.remove(name)
314
Antoine Pitroudbec7802010-10-10 09:37:12 +0000315 # strip spurious spaces
316 for k, v in done.items():
317 if isinstance(v, str):
318 done[k] = v.strip()
319
Tarek Ziadéedacea32010-01-29 11:41:03 +0000320 # save the results in the global dictionary
321 vars.update(done)
322 return vars
323
Tarek Ziadéedacea32010-01-29 11:41:03 +0000324
Barry Warsawebbef6f2010-09-20 15:29:53 +0000325def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000326 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000327 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100328 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200329 if hasattr(sys, 'abiflags'):
330 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
331 else:
332 config_dir_name = 'config'
333 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000334
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200335def _generate_posix_vars():
336 """Generate the Python module containing build-time variables."""
337 import pprint
338 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000339 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000340 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000341 try:
342 _parse_makefile(makefile, vars)
343 except IOError as e:
344 msg = "invalid Python installation: unable to open %s" % makefile
345 if hasattr(e, "strerror"):
346 msg = msg + " (%s)" % e.strerror
347 raise IOError(msg)
348 # load the installed pyconfig.h:
349 config_h = get_config_h_filename()
350 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000351 with open(config_h) as f:
352 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000353 except IOError as e:
354 msg = "invalid Python installation: unable to open %s" % config_h
355 if hasattr(e, "strerror"):
356 msg = msg + " (%s)" % e.strerror
357 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000358 # On AIX, there are wrong paths to the linker scripts in the Makefile
359 # -- these paths are relative to the Python source, but when installed
360 # the scripts are in another directory.
361 if _PYTHON_BUILD:
362 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200363
364 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200365 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200366 f.write('# system configuration generated and used by'
367 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200368 f.write('build_time_vars = ')
369 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000370
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200371def _init_posix(vars):
372 """Initialize the module as appropriate for POSIX systems."""
373 # _sysconfigdata is generated at build time, see _generate_posix_vars()
374 from _sysconfigdata import build_time_vars
375 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200376
Tarek Ziadéedacea32010-01-29 11:41:03 +0000377def _init_non_posix(vars):
378 """Initialize the module as appropriate for NT"""
379 # set basic install directories
380 vars['LIBDEST'] = get_path('stdlib')
381 vars['BINLIBDEST'] = get_path('platstdlib')
382 vars['INCLUDEPY'] = get_path('include')
383 vars['SO'] = '.pyd'
384 vars['EXE'] = '.exe'
385 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000386 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000387
388#
389# public APIs
390#
391
Tarek Ziadébd797682010-02-02 23:16:13 +0000392
393def parse_config_h(fp, vars=None):
394 """Parse a config.h-style file.
395
396 A dictionary containing name/value pairs is returned. If an
397 optional dictionary is passed in as the second argument, it is
398 used instead of a new dictionary.
399 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000400 if vars is None:
401 vars = {}
402 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
403 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
404
405 while True:
406 line = fp.readline()
407 if not line:
408 break
409 m = define_rx.match(line)
410 if m:
411 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200412 try:
413 v = int(v)
414 except ValueError:
415 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000416 vars[n] = v
417 else:
418 m = undef_rx.match(line)
419 if m:
420 vars[m.group(1)] = 0
421 return vars
422
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200423
Tarek Ziadébd797682010-02-02 23:16:13 +0000424def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000425 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000426 if _PYTHON_BUILD:
427 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100428 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000429 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100430 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000431 else:
432 inc_dir = get_path('platinclude')
433 return os.path.join(inc_dir, 'pyconfig.h')
434
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200435
Tarek Ziadéedacea32010-01-29 11:41:03 +0000436def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000437 """Return a tuple containing the schemes names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200438 return tuple(sorted(_SCHEMES.sections()))
439
Tarek Ziadéedacea32010-01-29 11:41:03 +0000440
441def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000442 """Return a tuple containing the paths names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200443 # xxx see if we want a static list
444 return _SCHEMES.options('posix_prefix')
445
Tarek Ziadéedacea32010-01-29 11:41:03 +0000446
447def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000448 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000449
450 ``scheme`` is the install scheme name. If not provided, it will
451 return the default scheme for the current platform.
452 """
453 if expand:
454 return _expand_vars(scheme, vars)
455 else:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200456 return dict(_SCHEMES.items(scheme))
457
Tarek Ziadéedacea32010-01-29 11:41:03 +0000458
459def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000460 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000461
462 ``scheme`` is the install scheme name.
463 """
464 return get_paths(scheme, vars, expand)[name]
465
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200466
Tarek Ziadéedacea32010-01-29 11:41:03 +0000467def get_config_vars(*args):
468 """With no arguments, return a dictionary of all configuration
469 variables relevant for the current platform.
470
471 On Unix, this means every variable defined in Python's installed Makefile;
472 On Windows and Mac OS it's a much smaller set.
473
474 With arguments, return a list of values that result from looking up
475 each argument in the configuration variable dictionary.
476 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000477 global _CONFIG_VARS
478 if _CONFIG_VARS is None:
479 _CONFIG_VARS = {}
480 # Normalized versions of prefix and exec_prefix are handy to have;
481 # in fact, these are the standard versions used most places in the
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200482 # packaging module.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000483 _CONFIG_VARS['prefix'] = _PREFIX
484 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
485 _CONFIG_VARS['py_version'] = _PY_VERSION
486 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
487 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100488 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100490 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000491 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000492 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000493 try:
494 _CONFIG_VARS['abiflags'] = sys.abiflags
495 except AttributeError:
496 # sys.abiflags may not be defined on all platforms.
497 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000498
499 if os.name in ('nt', 'os2'):
500 _init_non_posix(_CONFIG_VARS)
501 if os.name == 'posix':
502 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000503 # Setting 'userbase' is done below the call to the
504 # init function to enable using 'get_config_var' in
505 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100506 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000507
Tarek Ziadéedacea32010-01-29 11:41:03 +0000508 if 'srcdir' not in _CONFIG_VARS:
509 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000510 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000511 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000512
Tarek Ziadéedacea32010-01-29 11:41:03 +0000513 # Convert srcdir into an absolute path if it appears necessary.
514 # Normally it is relative to the build directory. However, during
515 # testing, for example, we might be running a non-installed python
516 # from a different directory.
517 if _PYTHON_BUILD and os.name == "posix":
518 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000519 try:
520 cwd = os.getcwd()
521 except OSError:
522 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000523 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000524 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000525 # srcdir is relative and we are not in the same directory
526 # as the executable. Assume executable is in the build
527 # directory and make srcdir absolute.
528 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
529 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
530
531 if sys.platform == 'darwin':
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200532 kernel_version = os.uname()[2] # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000533 major_version = int(kernel_version.split('.')[0])
534
535 if major_version < 8:
536 # On Mac OS X before 10.4, check if -arch and -isysroot
537 # are in CFLAGS or LDFLAGS and remove them if they are.
538 # This is needed when building extensions on a 10.3 system
539 # using a universal build of python.
540 for key in ('LDFLAGS', 'BASECFLAGS',
541 # a number of derived variables. These need to be
542 # patched up as well.
543 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
544 flags = _CONFIG_VARS[key]
545 flags = re.sub('-arch\s+\w+\s', ' ', flags)
546 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
547 _CONFIG_VARS[key] = flags
548 else:
549 # Allow the user to override the architecture flags using
550 # an environment variable.
551 # NOTE: This name was introduced by Apple in OSX 10.5 and
552 # is used by several scripting languages distributed with
553 # that OS release.
554 if 'ARCHFLAGS' in os.environ:
555 arch = os.environ['ARCHFLAGS']
556 for key in ('LDFLAGS', 'BASECFLAGS',
557 # a number of derived variables. These need to be
558 # patched up as well.
559 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
560
561 flags = _CONFIG_VARS[key]
562 flags = re.sub('-arch\s+\w+\s', ' ', flags)
563 flags = flags + ' ' + arch
564 _CONFIG_VARS[key] = flags
565
566 # If we're on OSX 10.5 or later and the user tries to
567 # compiles an extension using an SDK that is not present
568 # on the current machine it is better to not use an SDK
569 # than to fail.
570 #
571 # The major usecase for this is users using a Python.org
572 # binary installer on OSX 10.6: that installer uses
573 # the 10.4u SDK, but that SDK is not installed by default
574 # when you install Xcode.
575 #
576 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
577 m = re.search('-isysroot\s+(\S+)', CFLAGS)
578 if m is not None:
579 sdk = m.group(1)
580 if not os.path.exists(sdk):
581 for key in ('LDFLAGS', 'BASECFLAGS',
582 # a number of derived variables. These need to be
583 # patched up as well.
584 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
585
586 flags = _CONFIG_VARS[key]
587 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
588 _CONFIG_VARS[key] = flags
589
590 if args:
591 vals = []
592 for name in args:
593 vals.append(_CONFIG_VARS.get(name))
594 return vals
595 else:
596 return _CONFIG_VARS
597
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200598
Tarek Ziadéedacea32010-01-29 11:41:03 +0000599def get_config_var(name):
600 """Return the value of a single variable using the dictionary returned by
601 'get_config_vars()'.
602
603 Equivalent to get_config_vars().get(name)
604 """
605 return get_config_vars().get(name)
606
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200607
Tarek Ziadéedacea32010-01-29 11:41:03 +0000608def get_platform():
609 """Return a string that identifies the current platform.
610
611 This is used mainly to distinguish platform-specific build directories and
612 platform-specific built distributions. Typically includes the OS name
613 and version and the architecture (as supplied by 'os.uname()'),
614 although the exact information included depends on the OS; eg. for IRIX
615 the architecture isn't particularly important (IRIX only runs on SGI
616 hardware), but for Linux the kernel version isn't particularly
617 important.
618
619 Examples of returned values:
620 linux-i586
621 linux-alpha (?)
622 solaris-2.6-sun4u
623 irix-5.3
624 irix64-6.2
625
626 Windows will return one of:
627 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
628 win-ia64 (64bit Windows on Itanium)
629 win32 (all others - specifically, sys.platform is returned)
630
631 For other non-POSIX platforms, currently just returns 'sys.platform'.
632 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000633 if os.name == 'nt':
634 # sniff sys.version for architecture.
635 prefix = " bit ("
636 i = sys.version.find(prefix)
637 if i == -1:
638 return sys.platform
639 j = sys.version.find(")", i)
640 look = sys.version[i+len(prefix):j].lower()
641 if look == 'amd64':
642 return 'win-amd64'
643 if look == 'itanium':
644 return 'win-ia64'
645 return sys.platform
646
647 if os.name != "posix" or not hasattr(os, 'uname'):
648 # XXX what about the architecture? NT is Intel or Alpha,
649 # Mac OS is M68k or PPC, etc.
650 return sys.platform
651
652 # Try to distinguish various flavours of Unix
653 osname, host, release, version, machine = os.uname()
654
655 # Convert the OS name to lowercase, remove '/' characters
656 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
657 osname = osname.lower().replace('/', '')
658 machine = machine.replace(' ', '_')
659 machine = machine.replace('/', '-')
660
661 if osname[:5] == "linux":
662 # At least on Linux/Intel, 'machine' is the processor --
663 # i386, etc.
664 # XXX what about Alpha, SPARC, etc?
665 return "%s-%s" % (osname, machine)
666 elif osname[:5] == "sunos":
667 if release[0] >= "5": # SunOS 5 == Solaris 2
668 osname = "solaris"
669 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100670 # We can't use "platform.architecture()[0]" because a
671 # bootstrap problem. We use a dict to get an error
672 # if some suspicious happens.
673 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100674 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000675 # fall through to standard osname-release-machine representation
676 elif osname[:4] == "irix": # could be "irix64"!
677 return "%s-%s" % (osname, release)
678 elif osname[:3] == "aix":
679 return "%s-%s.%s" % (osname, version, release)
680 elif osname[:6] == "cygwin":
681 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200682 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000683 m = rel_re.match(release)
684 if m:
685 release = m.group()
686 elif osname[:6] == "darwin":
687 #
688 # For our purposes, we'll assume that the system version from
689 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
690 # to. This makes the compatibility story a bit more sane because the
691 # machine is going to compile and link as if it were
692 # MACOSX_DEPLOYMENT_TARGET.
693 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200694 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000695
Éric Araujo559b5f12011-05-25 18:21:43 +0200696 if True:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000697 # Always calculate the release of the running machine,
698 # needed to determine if we can build fat binaries or not.
699
700 macrelease = macver
701 # Get the system version. Reading this plist is a documented
702 # way to get the system version (see the documentation for
703 # the Gestalt Manager)
704 try:
705 f = open('/System/Library/CoreServices/SystemVersion.plist')
706 except IOError:
707 # We're on a plain darwin box, fall back to the default
708 # behaviour.
709 pass
710 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000711 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200712 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
713 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000714 finally:
715 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200716 if m is not None:
717 macrelease = '.'.join(m.group(1).split('.')[:2])
718 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000719
720 if not macver:
721 macver = macrelease
722
723 if macver:
724 release = macver
725 osname = "macosx"
726
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200727 if ((macrelease + '.') >= '10.4.' and
728 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000729 # The universal build will build fat binaries, but not on
730 # systems before 10.4
731 #
732 # Try to detect 4-way universal builds, those have machine-type
733 # 'universal' instead of 'fat'.
734
735 machine = 'fat'
736 cflags = get_config_vars().get('CFLAGS')
737
738 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000739 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000740
741 if len(archs) == 1:
742 machine = archs[0]
743 elif archs == ('i386', 'ppc'):
744 machine = 'fat'
745 elif archs == ('i386', 'x86_64'):
746 machine = 'intel'
747 elif archs == ('i386', 'ppc', 'x86_64'):
748 machine = 'fat3'
749 elif archs == ('ppc64', 'x86_64'):
750 machine = 'fat64'
751 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
752 machine = 'universal'
753 else:
754 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200755 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000756
757 elif machine == 'i386':
758 # On OSX the machine type returned by uname is always the
759 # 32-bit variant, even if the executable architecture is
760 # the 64-bit variant
761 if sys.maxsize >= 2**32:
762 machine = 'x86_64'
763
764 elif machine in ('PowerPC', 'Power_Macintosh'):
765 # Pick a sane name for the PPC architecture.
766 # See 'i386' case
767 if sys.maxsize >= 2**32:
768 machine = 'ppc64'
769 else:
770 machine = 'ppc'
771
772 return "%s-%s-%s" % (osname, release, machine)
773
774
775def get_python_version():
776 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000777
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200778
Tarek Ziadéa7514992010-05-25 09:44:36 +0000779def _print_dict(title, data):
780 for index, (key, value) in enumerate(sorted(data.items())):
781 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200782 print('%s: ' % (title))
783 print('\t%s = "%s"' % (key, value))
784
Tarek Ziadéa7514992010-05-25 09:44:36 +0000785
786def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000787 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200788 if '--generate-posix-vars' in sys.argv:
789 _generate_posix_vars()
790 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200791 print('Platform: "%s"' % get_platform())
792 print('Python version: "%s"' % get_python_version())
793 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200794 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000795 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200796 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000797 _print_dict('Variables', get_config_vars())
798
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200799
Tarek Ziadéa7514992010-05-25 09:44:36 +0000800if __name__ == '__main__':
801 _main()