blob: 4c1fd1bf2d51193711dc7c2d46250cca86253c24 [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 Ziade1231a4e2011-05-19 13:07:25 +02007from configparser import RawConfigParser
Tarek Ziadéedacea32010-01-29 11:41:03 +00008
Barry Warsawebbef6f2010-09-20 15:29:53 +00009__all__ = [
10 'get_config_h_filename',
11 'get_config_var',
12 'get_config_vars',
13 'get_makefile_filename',
14 'get_path',
15 'get_path_names',
16 'get_paths',
17 'get_platform',
18 'get_python_version',
19 'get_scheme_names',
20 'parse_config_h',
Tarek Ziade1231a4e2011-05-19 13:07:25 +020021]
Tarek Ziadé16ed6cb2010-05-25 09:47:06 +000022
Tarek Ziade1231a4e2011-05-19 13:07:25 +020023# let's read the configuration file
24# XXX _CONFIG_DIR will be set by the Makefile later
25_CONFIG_DIR = os.path.normpath(os.path.dirname(__file__))
26_CONFIG_FILE = os.path.join(_CONFIG_DIR, 'sysconfig.cfg')
27_SCHEMES = RawConfigParser()
28_SCHEMES.read(_CONFIG_FILE)
29_VAR_REPL = re.compile(r'\{([^{]*?)\}')
Tarek Ziadéedacea32010-01-29 11:41:03 +000030
Tarek Ziade1231a4e2011-05-19 13:07:25 +020031
32def _expand_globals(config):
33 if config.has_section('globals'):
34 globals = config.items('globals')
35 else:
36 globals = tuple()
37
38 sections = config.sections()
39 for section in sections:
40 if section == 'globals':
41 continue
42 for option, value in globals:
43 if config.has_option(section, option):
44 continue
45 config.set(section, option, value)
46 config.remove_section('globals')
47
48 # now expanding local variables defined in the cfg file
49 #
50 for section in config.sections():
51 variables = dict(config.items(section))
52
53 def _replacer(matchobj):
54 name = matchobj.group(1)
55 if name in variables:
56 return variables[name]
57 return matchobj.group(0)
58
59 for option, value in config.items(section):
60 config.set(section, option, _VAR_REPL.sub(_replacer, value))
61
62_expand_globals(_SCHEMES)
63
64 # FIXME don't rely on sys.version here, its format is an implementatin detail
65 # of CPython, use sys.version_info or sys.hexversion
Tarek Ziadéedacea32010-01-29 11:41:03 +000066_PY_VERSION = sys.version.split()[0]
67_PY_VERSION_SHORT = sys.version[:3]
68_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
69_PREFIX = os.path.normpath(sys.prefix)
70_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
71_CONFIG_VARS = None
72_USER_BASE = None
Victor Stinnerb103a932010-10-12 22:23:23 +000073
Tarek Ziade1231a4e2011-05-19 13:07:25 +020074
Victor Stinnerb103a932010-10-12 22:23:23 +000075def _safe_realpath(path):
76 try:
77 return realpath(path)
78 except OSError:
79 return path
80
Victor Stinner171ba052010-03-12 14:20:59 +000081if sys.executable:
Victor Stinnerb103a932010-10-12 22:23:23 +000082 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner171ba052010-03-12 14:20:59 +000083else:
84 # sys.executable can be empty if argv[0] has been changed and Python is
85 # unable to retrieve the real program name
Victor Stinnerb103a932010-10-12 22:23:23 +000086 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadéedacea32010-01-29 11:41:03 +000087
88if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +000089 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +000090# PC/VS7.1
91if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerb103a932010-10-12 22:23:23 +000092 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadéedacea32010-01-29 11:41:03 +000093# PC/AMD64
94if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].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
Tarek Ziade1231a4e2011-05-19 13:07:25 +020097
Tarek Ziadéedacea32010-01-29 11:41:03 +000098def is_python_build():
99 for fn in ("Setup.dist", "Setup.local"):
100 if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
101 return True
102 return False
103
104_PYTHON_BUILD = is_python_build()
105
106if _PYTHON_BUILD:
107 for scheme in ('posix_prefix', 'posix_home'):
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200108 _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
109 _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000110
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200111
112def _subst_vars(path, local_vars):
113 """In the string `path`, replace tokens like {some.thing} with the
114 corresponding value from the map `local_vars`.
115
116 If there is no corresponding value, leave the token unchanged.
117 """
118 def _replacer(matchobj):
119 name = matchobj.group(1)
120 if name in local_vars:
121 return local_vars[name]
122 elif name in os.environ:
123 return os.environ[name]
124 return matchobj.group(0)
125 return _VAR_REPL.sub(_replacer, path)
126
Tarek Ziadéedacea32010-01-29 11:41:03 +0000127
128def _extend_dict(target_dict, other_dict):
129 target_keys = target_dict.keys()
130 for key, value in other_dict.items():
131 if key in target_keys:
132 continue
133 target_dict[key] = value
134
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200135
Tarek Ziadéedacea32010-01-29 11:41:03 +0000136def _expand_vars(scheme, vars):
137 res = {}
138 if vars is None:
139 vars = {}
140 _extend_dict(vars, get_config_vars())
141
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200142 for key, value in _SCHEMES.items(scheme):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000143 if os.name in ('posix', 'nt'):
144 value = os.path.expanduser(value)
145 res[key] = os.path.normpath(_subst_vars(value, vars))
146 return res
147
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200148
149def format_value(value, vars):
150 def _replacer(matchobj):
151 name = matchobj.group(1)
152 if name in vars:
153 return vars[name]
154 return matchobj.group(0)
155 return _VAR_REPL.sub(_replacer, value)
156
157
Tarek Ziadéedacea32010-01-29 11:41:03 +0000158def _get_default_scheme():
159 if os.name == 'posix':
160 # the default scheme for posix is posix_prefix
161 return 'posix_prefix'
162 return os.name
163
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200164
Tarek Ziadéedacea32010-01-29 11:41:03 +0000165def _getuserbase():
166 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200167
Tarek Ziadéedacea32010-01-29 11:41:03 +0000168 def joinuser(*args):
169 return os.path.expanduser(os.path.join(*args))
170
171 # what about 'os2emx', 'riscos' ?
172 if os.name == "nt":
173 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200174 if env_base:
175 return env_base
176 else:
177 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000178
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000179 if sys.platform == "darwin":
180 framework = get_config_var("PYTHONFRAMEWORK")
181 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200182 if env_base:
183 return env_base
184 else:
185 return joinuser("~", "Library", framework, "%d.%d" %
186 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000187
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200188 if env_base:
189 return env_base
190 else:
191 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000192
193
194def _parse_makefile(filename, vars=None):
195 """Parse a Makefile-style file.
196
197 A dictionary containing name/value pairs is returned. If an
198 optional dictionary is passed in as the second argument, it is
199 used instead of a new dictionary.
200 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000201 # Regexes needed for parsing Makefile (and similar syntaxes,
202 # like old-style Setup files).
203 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
204 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
205 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
206
207 if vars is None:
208 vars = {}
209 done = {}
210 notdone = {}
211
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000212 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000213 lines = f.readlines()
214
215 for line in lines:
216 if line.startswith('#') or line.strip() == '':
217 continue
218 m = _variable_rx.match(line)
219 if m:
220 n, v = m.group(1, 2)
221 v = v.strip()
222 # `$$' is a literal `$' in make
223 tmpv = v.replace('$$', '')
224
225 if "$" in tmpv:
226 notdone[n] = v
227 else:
228 try:
229 v = int(v)
230 except ValueError:
231 # insert literal `$'
232 done[n] = v.replace('$$', '$')
233 else:
234 done[n] = v
235
236 # do variable interpolation here
237 variables = list(notdone.keys())
238
Ronald Oussorend21886c2010-07-20 16:07:10 +0000239 # Variables with a 'PY_' prefix in the makefile. These need to
240 # be made available without that prefix through sysconfig.
241 # Special care is needed to ensure that variable expansion works, even
242 # if the expansion uses the name without a prefix.
243 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
244
Tarek Ziadéedacea32010-01-29 11:41:03 +0000245 while len(variables) > 0:
246 for name in tuple(variables):
247 value = notdone[name]
248 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
249 if m is not None:
250 n = m.group(1)
251 found = True
252 if n in done:
253 item = str(done[n])
254 elif n in notdone:
255 # get it on a subsequent round
256 found = False
257 elif n in os.environ:
258 # do it like make: fall back to environment
259 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000260
261 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200262 if (name.startswith('PY_') and
263 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000264 item = ""
265
266 elif 'PY_' + n in notdone:
267 found = False
268
269 else:
270 item = str(done['PY_' + n])
271
Tarek Ziadéedacea32010-01-29 11:41:03 +0000272 else:
273 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000274
Tarek Ziadéedacea32010-01-29 11:41:03 +0000275 if found:
276 after = value[m.end():]
277 value = value[:m.start()] + item + after
278 if "$" in after:
279 notdone[name] = value
280 else:
281 try:
282 value = int(value)
283 except ValueError:
284 done[name] = value.strip()
285 else:
286 done[name] = value
287 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000288
289 if name.startswith('PY_') \
290 and name[3:] in renamed_variables:
291
292 name = name[3:]
293 if name not in done:
294 done[name] = value
295
Tarek Ziadéedacea32010-01-29 11:41:03 +0000296 else:
297 # bogus variable reference; just drop it since we can't deal
298 variables.remove(name)
299
Antoine Pitroudbec7802010-10-10 09:37:12 +0000300 # strip spurious spaces
301 for k, v in done.items():
302 if isinstance(v, str):
303 done[k] = v.strip()
304
Tarek Ziadéedacea32010-01-29 11:41:03 +0000305 # save the results in the global dictionary
306 vars.update(done)
307 return vars
308
Tarek Ziadéedacea32010-01-29 11:41:03 +0000309
Barry Warsawebbef6f2010-09-20 15:29:53 +0000310def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000311 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000312 if _PYTHON_BUILD:
313 return os.path.join(_PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200314 if hasattr(sys, 'abiflags'):
315 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
316 else:
317 config_dir_name = 'config'
318 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000319
Tarek Ziadéedacea32010-01-29 11:41:03 +0000320
321def _init_posix(vars):
322 """Initialize the module as appropriate for POSIX systems."""
323 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000324 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000325 try:
326 _parse_makefile(makefile, vars)
327 except IOError as e:
328 msg = "invalid Python installation: unable to open %s" % makefile
329 if hasattr(e, "strerror"):
330 msg = msg + " (%s)" % e.strerror
331 raise IOError(msg)
332 # load the installed pyconfig.h:
333 config_h = get_config_h_filename()
334 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000335 with open(config_h) as f:
336 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000337 except IOError as e:
338 msg = "invalid Python installation: unable to open %s" % config_h
339 if hasattr(e, "strerror"):
340 msg = msg + " (%s)" % e.strerror
341 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000342 # On AIX, there are wrong paths to the linker scripts in the Makefile
343 # -- these paths are relative to the Python source, but when installed
344 # the scripts are in another directory.
345 if _PYTHON_BUILD:
346 vars['LDSHARED'] = vars['BLDSHARED']
347
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200348
Tarek Ziadéedacea32010-01-29 11:41:03 +0000349def _init_non_posix(vars):
350 """Initialize the module as appropriate for NT"""
351 # set basic install directories
352 vars['LIBDEST'] = get_path('stdlib')
353 vars['BINLIBDEST'] = get_path('platstdlib')
354 vars['INCLUDEPY'] = get_path('include')
355 vars['SO'] = '.pyd'
356 vars['EXE'] = '.exe'
357 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000358 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000359
360#
361# public APIs
362#
363
Tarek Ziadébd797682010-02-02 23:16:13 +0000364
365def parse_config_h(fp, vars=None):
366 """Parse a config.h-style file.
367
368 A dictionary containing name/value pairs is returned. If an
369 optional dictionary is passed in as the second argument, it is
370 used instead of a new dictionary.
371 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000372 if vars is None:
373 vars = {}
374 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
375 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
376
377 while True:
378 line = fp.readline()
379 if not line:
380 break
381 m = define_rx.match(line)
382 if m:
383 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200384 try:
385 v = int(v)
386 except ValueError:
387 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000388 vars[n] = v
389 else:
390 m = undef_rx.match(line)
391 if m:
392 vars[m.group(1)] = 0
393 return vars
394
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200395
Tarek Ziadébd797682010-02-02 23:16:13 +0000396def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000397 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000398 if _PYTHON_BUILD:
399 if os.name == "nt":
400 inc_dir = os.path.join(_PROJECT_BASE, "PC")
401 else:
402 inc_dir = _PROJECT_BASE
403 else:
404 inc_dir = get_path('platinclude')
405 return os.path.join(inc_dir, 'pyconfig.h')
406
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200407
Tarek Ziadéedacea32010-01-29 11:41:03 +0000408def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000409 """Return a tuple containing the schemes names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200410 return tuple(sorted(_SCHEMES.sections()))
411
Tarek Ziadéedacea32010-01-29 11:41:03 +0000412
413def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000414 """Return a tuple containing the paths names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200415 # xxx see if we want a static list
416 return _SCHEMES.options('posix_prefix')
417
Tarek Ziadéedacea32010-01-29 11:41:03 +0000418
419def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000420 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000421
422 ``scheme`` is the install scheme name. If not provided, it will
423 return the default scheme for the current platform.
424 """
425 if expand:
426 return _expand_vars(scheme, vars)
427 else:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200428 return dict(_SCHEMES.items(scheme))
429
Tarek Ziadéedacea32010-01-29 11:41:03 +0000430
431def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000432 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000433
434 ``scheme`` is the install scheme name.
435 """
436 return get_paths(scheme, vars, expand)[name]
437
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200438
Tarek Ziadéedacea32010-01-29 11:41:03 +0000439def get_config_vars(*args):
440 """With no arguments, return a dictionary of all configuration
441 variables relevant for the current platform.
442
443 On Unix, this means every variable defined in Python's installed Makefile;
444 On Windows and Mac OS it's a much smaller set.
445
446 With arguments, return a list of values that result from looking up
447 each argument in the configuration variable dictionary.
448 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000449 global _CONFIG_VARS
450 if _CONFIG_VARS is None:
451 _CONFIG_VARS = {}
452 # Normalized versions of prefix and exec_prefix are handy to have;
453 # in fact, these are the standard versions used most places in the
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200454 # packaging module.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000455 _CONFIG_VARS['prefix'] = _PREFIX
456 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
457 _CONFIG_VARS['py_version'] = _PY_VERSION
458 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
459 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
460 _CONFIG_VARS['base'] = _PREFIX
461 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000462 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000463 try:
464 _CONFIG_VARS['abiflags'] = sys.abiflags
465 except AttributeError:
466 # sys.abiflags may not be defined on all platforms.
467 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000468
469 if os.name in ('nt', 'os2'):
470 _init_non_posix(_CONFIG_VARS)
471 if os.name == 'posix':
472 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000473 # Setting 'userbase' is done below the call to the
474 # init function to enable using 'get_config_var' in
475 # the init-function.
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200476 if sys.version >= '2.6':
477 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000478
Tarek Ziadéedacea32010-01-29 11:41:03 +0000479 if 'srcdir' not in _CONFIG_VARS:
480 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000481 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000482 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000483
Tarek Ziadéedacea32010-01-29 11:41:03 +0000484 # Convert srcdir into an absolute path if it appears necessary.
485 # Normally it is relative to the build directory. However, during
486 # testing, for example, we might be running a non-installed python
487 # from a different directory.
488 if _PYTHON_BUILD and os.name == "posix":
489 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000490 try:
491 cwd = os.getcwd()
492 except OSError:
493 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000494 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000495 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000496 # srcdir is relative and we are not in the same directory
497 # as the executable. Assume executable is in the build
498 # directory and make srcdir absolute.
499 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
500 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
501
502 if sys.platform == 'darwin':
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200503 kernel_version = os.uname()[2] # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000504 major_version = int(kernel_version.split('.')[0])
505
506 if major_version < 8:
507 # On Mac OS X before 10.4, check if -arch and -isysroot
508 # are in CFLAGS or LDFLAGS and remove them if they are.
509 # This is needed when building extensions on a 10.3 system
510 # using a universal build of python.
511 for key in ('LDFLAGS', 'BASECFLAGS',
512 # a number of derived variables. These need to be
513 # patched up as well.
514 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
515 flags = _CONFIG_VARS[key]
516 flags = re.sub('-arch\s+\w+\s', ' ', flags)
517 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
518 _CONFIG_VARS[key] = flags
519 else:
520 # Allow the user to override the architecture flags using
521 # an environment variable.
522 # NOTE: This name was introduced by Apple in OSX 10.5 and
523 # is used by several scripting languages distributed with
524 # that OS release.
525 if 'ARCHFLAGS' in os.environ:
526 arch = os.environ['ARCHFLAGS']
527 for key in ('LDFLAGS', 'BASECFLAGS',
528 # a number of derived variables. These need to be
529 # patched up as well.
530 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
531
532 flags = _CONFIG_VARS[key]
533 flags = re.sub('-arch\s+\w+\s', ' ', flags)
534 flags = flags + ' ' + arch
535 _CONFIG_VARS[key] = flags
536
537 # If we're on OSX 10.5 or later and the user tries to
538 # compiles an extension using an SDK that is not present
539 # on the current machine it is better to not use an SDK
540 # than to fail.
541 #
542 # The major usecase for this is users using a Python.org
543 # binary installer on OSX 10.6: that installer uses
544 # the 10.4u SDK, but that SDK is not installed by default
545 # when you install Xcode.
546 #
547 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
548 m = re.search('-isysroot\s+(\S+)', CFLAGS)
549 if m is not None:
550 sdk = m.group(1)
551 if not os.path.exists(sdk):
552 for key in ('LDFLAGS', 'BASECFLAGS',
553 # a number of derived variables. These need to be
554 # patched up as well.
555 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
556
557 flags = _CONFIG_VARS[key]
558 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
559 _CONFIG_VARS[key] = flags
560
561 if args:
562 vals = []
563 for name in args:
564 vals.append(_CONFIG_VARS.get(name))
565 return vals
566 else:
567 return _CONFIG_VARS
568
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200569
Tarek Ziadéedacea32010-01-29 11:41:03 +0000570def get_config_var(name):
571 """Return the value of a single variable using the dictionary returned by
572 'get_config_vars()'.
573
574 Equivalent to get_config_vars().get(name)
575 """
576 return get_config_vars().get(name)
577
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200578
Tarek Ziadéedacea32010-01-29 11:41:03 +0000579def get_platform():
580 """Return a string that identifies the current platform.
581
582 This is used mainly to distinguish platform-specific build directories and
583 platform-specific built distributions. Typically includes the OS name
584 and version and the architecture (as supplied by 'os.uname()'),
585 although the exact information included depends on the OS; eg. for IRIX
586 the architecture isn't particularly important (IRIX only runs on SGI
587 hardware), but for Linux the kernel version isn't particularly
588 important.
589
590 Examples of returned values:
591 linux-i586
592 linux-alpha (?)
593 solaris-2.6-sun4u
594 irix-5.3
595 irix64-6.2
596
597 Windows will return one of:
598 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
599 win-ia64 (64bit Windows on Itanium)
600 win32 (all others - specifically, sys.platform is returned)
601
602 For other non-POSIX platforms, currently just returns 'sys.platform'.
603 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000604 if os.name == 'nt':
605 # sniff sys.version for architecture.
606 prefix = " bit ("
607 i = sys.version.find(prefix)
608 if i == -1:
609 return sys.platform
610 j = sys.version.find(")", i)
611 look = sys.version[i+len(prefix):j].lower()
612 if look == 'amd64':
613 return 'win-amd64'
614 if look == 'itanium':
615 return 'win-ia64'
616 return sys.platform
617
618 if os.name != "posix" or not hasattr(os, 'uname'):
619 # XXX what about the architecture? NT is Intel or Alpha,
620 # Mac OS is M68k or PPC, etc.
621 return sys.platform
622
623 # Try to distinguish various flavours of Unix
624 osname, host, release, version, machine = os.uname()
625
626 # Convert the OS name to lowercase, remove '/' characters
627 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
628 osname = osname.lower().replace('/', '')
629 machine = machine.replace(' ', '_')
630 machine = machine.replace('/', '-')
631
632 if osname[:5] == "linux":
633 # At least on Linux/Intel, 'machine' is the processor --
634 # i386, etc.
635 # XXX what about Alpha, SPARC, etc?
636 return "%s-%s" % (osname, machine)
637 elif osname[:5] == "sunos":
638 if release[0] >= "5": # SunOS 5 == Solaris 2
639 osname = "solaris"
640 release = "%d.%s" % (int(release[0]) - 3, release[2:])
641 # fall through to standard osname-release-machine representation
642 elif osname[:4] == "irix": # could be "irix64"!
643 return "%s-%s" % (osname, release)
644 elif osname[:3] == "aix":
645 return "%s-%s.%s" % (osname, version, release)
646 elif osname[:6] == "cygwin":
647 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200648 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000649 m = rel_re.match(release)
650 if m:
651 release = m.group()
652 elif osname[:6] == "darwin":
653 #
654 # For our purposes, we'll assume that the system version from
655 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
656 # to. This makes the compatibility story a bit more sane because the
657 # machine is going to compile and link as if it were
658 # MACOSX_DEPLOYMENT_TARGET.
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200659 #
Tarek Ziadéedacea32010-01-29 11:41:03 +0000660 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200661 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000662
663 if 1:
664 # Always calculate the release of the running machine,
665 # needed to determine if we can build fat binaries or not.
666
667 macrelease = macver
668 # Get the system version. Reading this plist is a documented
669 # way to get the system version (see the documentation for
670 # the Gestalt Manager)
671 try:
672 f = open('/System/Library/CoreServices/SystemVersion.plist')
673 except IOError:
674 # We're on a plain darwin box, fall back to the default
675 # behaviour.
676 pass
677 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000678 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200679 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
680 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000681 finally:
682 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200683 if m is not None:
684 macrelease = '.'.join(m.group(1).split('.')[:2])
685 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000686
687 if not macver:
688 macver = macrelease
689
690 if macver:
691 release = macver
692 osname = "macosx"
693
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200694 if ((macrelease + '.') >= '10.4.' and
695 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000696 # The universal build will build fat binaries, but not on
697 # systems before 10.4
698 #
699 # Try to detect 4-way universal builds, those have machine-type
700 # 'universal' instead of 'fat'.
701
702 machine = 'fat'
703 cflags = get_config_vars().get('CFLAGS')
704
705 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000706 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000707
708 if len(archs) == 1:
709 machine = archs[0]
710 elif archs == ('i386', 'ppc'):
711 machine = 'fat'
712 elif archs == ('i386', 'x86_64'):
713 machine = 'intel'
714 elif archs == ('i386', 'ppc', 'x86_64'):
715 machine = 'fat3'
716 elif archs == ('ppc64', 'x86_64'):
717 machine = 'fat64'
718 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
719 machine = 'universal'
720 else:
721 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200722 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000723
724 elif machine == 'i386':
725 # On OSX the machine type returned by uname is always the
726 # 32-bit variant, even if the executable architecture is
727 # the 64-bit variant
728 if sys.maxsize >= 2**32:
729 machine = 'x86_64'
730
731 elif machine in ('PowerPC', 'Power_Macintosh'):
732 # Pick a sane name for the PPC architecture.
733 # See 'i386' case
734 if sys.maxsize >= 2**32:
735 machine = 'ppc64'
736 else:
737 machine = 'ppc'
738
739 return "%s-%s-%s" % (osname, release, machine)
740
741
742def get_python_version():
743 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000744
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200745
Tarek Ziadéa7514992010-05-25 09:44:36 +0000746def _print_dict(title, data):
747 for index, (key, value) in enumerate(sorted(data.items())):
748 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200749 print('%s: ' % (title))
750 print('\t%s = "%s"' % (key, value))
751
Tarek Ziadéa7514992010-05-25 09:44:36 +0000752
753def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000754 """Display all information sysconfig detains."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200755 print('Platform: "%s"' % get_platform())
756 print('Python version: "%s"' % get_python_version())
757 print('Current installation scheme: "%s"' % _get_default_scheme())
Tarek Ziadéa7514992010-05-25 09:44:36 +0000758 print('')
759 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200760 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000761 _print_dict('Variables', get_config_vars())
762
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200763
Tarek Ziadéa7514992010-05-25 09:44:36 +0000764if __name__ == '__main__':
765 _main()