blob: 6ed9fd831f888a2127b08e856ff78199e345094f [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)
107if _sys_home and os.name == 'nt' and _sys_home.lower().endswith('pcbuild'):
108 _sys_home = os.path.dirname(_sys_home)
109
110def is_python_build(check_home=False):
111 if check_home and _sys_home:
112 return _is_python_source_dir(_sys_home)
113 return _is_python_source_dir(_PROJECT_BASE)
114
115_PYTHON_BUILD = is_python_build(True)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000116
117if _PYTHON_BUILD:
118 for scheme in ('posix_prefix', 'posix_home'):
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200119 _SCHEMES.set(scheme, 'include', '{srcdir}/Include')
120 _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000121
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200122
123def _subst_vars(path, local_vars):
124 """In the string `path`, replace tokens like {some.thing} with the
125 corresponding value from the map `local_vars`.
126
127 If there is no corresponding value, leave the token unchanged.
128 """
129 def _replacer(matchobj):
130 name = matchobj.group(1)
131 if name in local_vars:
132 return local_vars[name]
133 elif name in os.environ:
134 return os.environ[name]
135 return matchobj.group(0)
136 return _VAR_REPL.sub(_replacer, path)
137
Tarek Ziadéedacea32010-01-29 11:41:03 +0000138
139def _extend_dict(target_dict, other_dict):
140 target_keys = target_dict.keys()
141 for key, value in other_dict.items():
142 if key in target_keys:
143 continue
144 target_dict[key] = value
145
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200146
Tarek Ziadéedacea32010-01-29 11:41:03 +0000147def _expand_vars(scheme, vars):
148 res = {}
149 if vars is None:
150 vars = {}
151 _extend_dict(vars, get_config_vars())
152
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200153 for key, value in _SCHEMES.items(scheme):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000154 if os.name in ('posix', 'nt'):
155 value = os.path.expanduser(value)
156 res[key] = os.path.normpath(_subst_vars(value, vars))
157 return res
158
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200159
160def format_value(value, vars):
161 def _replacer(matchobj):
162 name = matchobj.group(1)
163 if name in vars:
164 return vars[name]
165 return matchobj.group(0)
166 return _VAR_REPL.sub(_replacer, value)
167
168
Tarek Ziadéedacea32010-01-29 11:41:03 +0000169def _get_default_scheme():
170 if os.name == 'posix':
171 # the default scheme for posix is posix_prefix
172 return 'posix_prefix'
173 return os.name
174
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200175
Tarek Ziadéedacea32010-01-29 11:41:03 +0000176def _getuserbase():
177 env_base = os.environ.get("PYTHONUSERBASE", None)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200178
Tarek Ziadéedacea32010-01-29 11:41:03 +0000179 def joinuser(*args):
180 return os.path.expanduser(os.path.join(*args))
181
182 # what about 'os2emx', 'riscos' ?
183 if os.name == "nt":
184 base = os.environ.get("APPDATA") or "~"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200185 if env_base:
186 return env_base
187 else:
188 return joinuser(base, "Python")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000189
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000190 if sys.platform == "darwin":
191 framework = get_config_var("PYTHONFRAMEWORK")
192 if framework:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200193 if env_base:
194 return env_base
195 else:
196 return joinuser("~", "Library", framework, "%d.%d" %
197 sys.version_info[:2])
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000198
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200199 if env_base:
200 return env_base
201 else:
202 return joinuser("~", ".local")
Tarek Ziadéedacea32010-01-29 11:41:03 +0000203
204
205def _parse_makefile(filename, vars=None):
206 """Parse a Makefile-style file.
207
208 A dictionary containing name/value pairs is returned. If an
209 optional dictionary is passed in as the second argument, it is
210 used instead of a new dictionary.
211 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000212 # Regexes needed for parsing Makefile (and similar syntaxes,
213 # like old-style Setup files).
214 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
215 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
216 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
217
218 if vars is None:
219 vars = {}
220 done = {}
221 notdone = {}
222
Victor Stinner75d8c5c2010-10-23 17:02:31 +0000223 with open(filename, errors="surrogateescape") as f:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000224 lines = f.readlines()
225
226 for line in lines:
227 if line.startswith('#') or line.strip() == '':
228 continue
229 m = _variable_rx.match(line)
230 if m:
231 n, v = m.group(1, 2)
232 v = v.strip()
233 # `$$' is a literal `$' in make
234 tmpv = v.replace('$$', '')
235
236 if "$" in tmpv:
237 notdone[n] = v
238 else:
239 try:
240 v = int(v)
241 except ValueError:
242 # insert literal `$'
243 done[n] = v.replace('$$', '$')
244 else:
245 done[n] = v
246
247 # do variable interpolation here
248 variables = list(notdone.keys())
249
Ronald Oussorend21886c2010-07-20 16:07:10 +0000250 # Variables with a 'PY_' prefix in the makefile. These need to
251 # be made available without that prefix through sysconfig.
252 # Special care is needed to ensure that variable expansion works, even
253 # if the expansion uses the name without a prefix.
254 renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS')
255
Tarek Ziadéedacea32010-01-29 11:41:03 +0000256 while len(variables) > 0:
257 for name in tuple(variables):
258 value = notdone[name]
259 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
260 if m is not None:
261 n = m.group(1)
262 found = True
263 if n in done:
264 item = str(done[n])
265 elif n in notdone:
266 # get it on a subsequent round
267 found = False
268 elif n in os.environ:
269 # do it like make: fall back to environment
270 item = os.environ[n]
Ronald Oussorend21886c2010-07-20 16:07:10 +0000271
272 elif n in renamed_variables:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200273 if (name.startswith('PY_') and
274 name[3:] in renamed_variables):
Ronald Oussorend21886c2010-07-20 16:07:10 +0000275 item = ""
276
277 elif 'PY_' + n in notdone:
278 found = False
279
280 else:
281 item = str(done['PY_' + n])
282
Tarek Ziadéedacea32010-01-29 11:41:03 +0000283 else:
284 done[n] = item = ""
Ronald Oussorend21886c2010-07-20 16:07:10 +0000285
Tarek Ziadéedacea32010-01-29 11:41:03 +0000286 if found:
287 after = value[m.end():]
288 value = value[:m.start()] + item + after
289 if "$" in after:
290 notdone[name] = value
291 else:
292 try:
293 value = int(value)
294 except ValueError:
295 done[name] = value.strip()
296 else:
297 done[name] = value
298 variables.remove(name)
Ronald Oussorend21886c2010-07-20 16:07:10 +0000299
300 if name.startswith('PY_') \
Victor Stinner1273b7c2011-05-24 23:37:07 +0200301 and name[3:] in renamed_variables:
Ronald Oussorend21886c2010-07-20 16:07:10 +0000302
303 name = name[3:]
304 if name not in done:
305 done[name] = value
306
Tarek Ziadéedacea32010-01-29 11:41:03 +0000307 else:
Victor Stinner1273b7c2011-05-24 23:37:07 +0200308 # bogus variable reference (e.g. "prefix=$/opt/python");
309 # just drop it since we can't deal
310 done[name] = value
Tarek Ziadéedacea32010-01-29 11:41:03 +0000311 variables.remove(name)
312
Antoine Pitroudbec7802010-10-10 09:37:12 +0000313 # strip spurious spaces
314 for k, v in done.items():
315 if isinstance(v, str):
316 done[k] = v.strip()
317
Tarek Ziadéedacea32010-01-29 11:41:03 +0000318 # save the results in the global dictionary
319 vars.update(done)
320 return vars
321
Tarek Ziadéedacea32010-01-29 11:41:03 +0000322
Barry Warsawebbef6f2010-09-20 15:29:53 +0000323def get_makefile_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000324 """Return the path of the Makefile."""
Tarek Ziadéedacea32010-01-29 11:41:03 +0000325 if _PYTHON_BUILD:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100326 return os.path.join(_sys_home or _PROJECT_BASE, "Makefile")
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200327 if hasattr(sys, 'abiflags'):
328 config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags)
329 else:
330 config_dir_name = 'config'
331 return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000332
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200333def _generate_posix_vars():
334 """Generate the Python module containing build-time variables."""
335 import pprint
336 vars = {}
Tarek Ziadéedacea32010-01-29 11:41:03 +0000337 # load the installed Makefile:
Barry Warsawebbef6f2010-09-20 15:29:53 +0000338 makefile = get_makefile_filename()
Tarek Ziadéedacea32010-01-29 11:41:03 +0000339 try:
340 _parse_makefile(makefile, vars)
341 except IOError as e:
342 msg = "invalid Python installation: unable to open %s" % makefile
343 if hasattr(e, "strerror"):
344 msg = msg + " (%s)" % e.strerror
345 raise IOError(msg)
346 # load the installed pyconfig.h:
347 config_h = get_config_h_filename()
348 try:
Antoine Pitroub86680e2010-10-14 21:15:17 +0000349 with open(config_h) as f:
350 parse_config_h(f, vars)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000351 except IOError as e:
352 msg = "invalid Python installation: unable to open %s" % config_h
353 if hasattr(e, "strerror"):
354 msg = msg + " (%s)" % e.strerror
355 raise IOError(msg)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000356 # On AIX, there are wrong paths to the linker scripts in the Makefile
357 # -- these paths are relative to the Python source, but when installed
358 # the scripts are in another directory.
359 if _PYTHON_BUILD:
360 vars['LDSHARED'] = vars['BLDSHARED']
Victor Stinner65651ea2011-10-20 00:41:21 +0200361
362 destfile = os.path.join(os.path.dirname(__file__), '_sysconfigdata.py')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200363 with open(destfile, 'w', encoding='utf8') as f:
Victor Stinner65651ea2011-10-20 00:41:21 +0200364 f.write('# system configuration generated and used by'
365 ' the sysconfig module\n')
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200366 f.write('build_time_vars = ')
367 pprint.pprint(vars, stream=f)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000368
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200369def _init_posix(vars):
370 """Initialize the module as appropriate for POSIX systems."""
371 # _sysconfigdata is generated at build time, see _generate_posix_vars()
372 from _sysconfigdata import build_time_vars
373 vars.update(build_time_vars)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200374
Tarek Ziadéedacea32010-01-29 11:41:03 +0000375def _init_non_posix(vars):
376 """Initialize the module as appropriate for NT"""
377 # set basic install directories
378 vars['LIBDEST'] = get_path('stdlib')
379 vars['BINLIBDEST'] = get_path('platstdlib')
380 vars['INCLUDEPY'] = get_path('include')
381 vars['SO'] = '.pyd'
382 vars['EXE'] = '.exe'
383 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerb103a932010-10-12 22:23:23 +0000384 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000385
386#
387# public APIs
388#
389
Tarek Ziadébd797682010-02-02 23:16:13 +0000390
391def parse_config_h(fp, vars=None):
392 """Parse a config.h-style file.
393
394 A dictionary containing name/value pairs is returned. If an
395 optional dictionary is passed in as the second argument, it is
396 used instead of a new dictionary.
397 """
Tarek Ziadébd797682010-02-02 23:16:13 +0000398 if vars is None:
399 vars = {}
400 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
401 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
402
403 while True:
404 line = fp.readline()
405 if not line:
406 break
407 m = define_rx.match(line)
408 if m:
409 n, v = m.group(1, 2)
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200410 try:
411 v = int(v)
412 except ValueError:
413 pass
Tarek Ziadébd797682010-02-02 23:16:13 +0000414 vars[n] = v
415 else:
416 m = undef_rx.match(line)
417 if m:
418 vars[m.group(1)] = 0
419 return vars
420
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200421
Tarek Ziadébd797682010-02-02 23:16:13 +0000422def get_config_h_filename():
Éric Araujo300623d2010-11-22 01:19:20 +0000423 """Return the path of pyconfig.h."""
Tarek Ziadébd797682010-02-02 23:16:13 +0000424 if _PYTHON_BUILD:
425 if os.name == "nt":
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100426 inc_dir = os.path.join(_sys_home or _PROJECT_BASE, "PC")
Tarek Ziadébd797682010-02-02 23:16:13 +0000427 else:
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100428 inc_dir = _sys_home or _PROJECT_BASE
Tarek Ziadébd797682010-02-02 23:16:13 +0000429 else:
430 inc_dir = get_path('platinclude')
431 return os.path.join(inc_dir, 'pyconfig.h')
432
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200433
Tarek Ziadéedacea32010-01-29 11:41:03 +0000434def get_scheme_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000435 """Return a tuple containing the schemes names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200436 return tuple(sorted(_SCHEMES.sections()))
437
Tarek Ziadéedacea32010-01-29 11:41:03 +0000438
439def get_path_names():
Éric Araujo300623d2010-11-22 01:19:20 +0000440 """Return a tuple containing the paths names."""
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200441 # xxx see if we want a static list
442 return _SCHEMES.options('posix_prefix')
443
Tarek Ziadéedacea32010-01-29 11:41:03 +0000444
445def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000446 """Return a mapping containing an install scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000447
448 ``scheme`` is the install scheme name. If not provided, it will
449 return the default scheme for the current platform.
450 """
451 if expand:
452 return _expand_vars(scheme, vars)
453 else:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200454 return dict(_SCHEMES.items(scheme))
455
Tarek Ziadéedacea32010-01-29 11:41:03 +0000456
457def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
Éric Araujo300623d2010-11-22 01:19:20 +0000458 """Return a path corresponding to the scheme.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000459
460 ``scheme`` is the install scheme name.
461 """
462 return get_paths(scheme, vars, expand)[name]
463
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200464
Tarek Ziadéedacea32010-01-29 11:41:03 +0000465def get_config_vars(*args):
466 """With no arguments, return a dictionary of all configuration
467 variables relevant for the current platform.
468
469 On Unix, this means every variable defined in Python's installed Makefile;
470 On Windows and Mac OS it's a much smaller set.
471
472 With arguments, return a list of values that result from looking up
473 each argument in the configuration variable dictionary.
474 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000475 global _CONFIG_VARS
476 if _CONFIG_VARS is None:
477 _CONFIG_VARS = {}
478 # Normalized versions of prefix and exec_prefix are handy to have;
479 # in fact, these are the standard versions used most places in the
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200480 # packaging module.
Tarek Ziadéedacea32010-01-29 11:41:03 +0000481 _CONFIG_VARS['prefix'] = _PREFIX
482 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
483 _CONFIG_VARS['py_version'] = _PY_VERSION
484 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
485 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100486 _CONFIG_VARS['installed_base'] = _BASE_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000487 _CONFIG_VARS['base'] = _PREFIX
Vinay Sajip7ded1f02012-05-26 03:45:29 +0100488 _CONFIG_VARS['installed_platbase'] = _BASE_EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000489 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadéedacea32010-01-29 11:41:03 +0000490 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
Barry Warsawd5eaa5f2010-11-25 01:34:47 +0000491 try:
492 _CONFIG_VARS['abiflags'] = sys.abiflags
493 except AttributeError:
494 # sys.abiflags may not be defined on all platforms.
495 _CONFIG_VARS['abiflags'] = ''
Tarek Ziadéedacea32010-01-29 11:41:03 +0000496
497 if os.name in ('nt', 'os2'):
498 _init_non_posix(_CONFIG_VARS)
499 if os.name == 'posix':
500 _init_posix(_CONFIG_VARS)
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000501 # Setting 'userbase' is done below the call to the
502 # init function to enable using 'get_config_var' in
503 # the init-function.
Éric Araujo2a7cc532011-11-07 09:18:30 +0100504 _CONFIG_VARS['userbase'] = _getuserbase()
Ronald Oussoren4cda46a2010-05-08 10:49:43 +0000505
Tarek Ziadéedacea32010-01-29 11:41:03 +0000506 if 'srcdir' not in _CONFIG_VARS:
507 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
Ronald Oussorenab4fd612010-06-15 21:19:50 +0000508 else:
Victor Stinnerb103a932010-10-12 22:23:23 +0000509 _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir'])
Tarek Ziadéedacea32010-01-29 11:41:03 +0000510
Tarek Ziadéedacea32010-01-29 11:41:03 +0000511 # Convert srcdir into an absolute path if it appears necessary.
512 # Normally it is relative to the build directory. However, during
513 # testing, for example, we might be running a non-installed python
514 # from a different directory.
515 if _PYTHON_BUILD and os.name == "posix":
516 base = _PROJECT_BASE
Victor Stinnerb103a932010-10-12 22:23:23 +0000517 try:
518 cwd = os.getcwd()
519 except OSError:
520 cwd = None
Tarek Ziadéedacea32010-01-29 11:41:03 +0000521 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerb103a932010-10-12 22:23:23 +0000522 base != cwd):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000523 # srcdir is relative and we are not in the same directory
524 # as the executable. Assume executable is in the build
525 # directory and make srcdir absolute.
526 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
527 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
528
529 if sys.platform == 'darwin':
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200530 kernel_version = os.uname()[2] # Kernel version (8.4.3)
Tarek Ziadéedacea32010-01-29 11:41:03 +0000531 major_version = int(kernel_version.split('.')[0])
532
533 if major_version < 8:
534 # On Mac OS X before 10.4, check if -arch and -isysroot
535 # are in CFLAGS or LDFLAGS and remove them if they are.
536 # This is needed when building extensions on a 10.3 system
537 # using a universal build of python.
538 for key in ('LDFLAGS', 'BASECFLAGS',
539 # a number of derived variables. These need to be
540 # patched up as well.
541 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
542 flags = _CONFIG_VARS[key]
543 flags = re.sub('-arch\s+\w+\s', ' ', flags)
544 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
545 _CONFIG_VARS[key] = flags
546 else:
547 # Allow the user to override the architecture flags using
548 # an environment variable.
549 # NOTE: This name was introduced by Apple in OSX 10.5 and
550 # is used by several scripting languages distributed with
551 # that OS release.
552 if 'ARCHFLAGS' in os.environ:
553 arch = os.environ['ARCHFLAGS']
554 for key in ('LDFLAGS', 'BASECFLAGS',
555 # a number of derived variables. These need to be
556 # patched up as well.
557 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
558
559 flags = _CONFIG_VARS[key]
560 flags = re.sub('-arch\s+\w+\s', ' ', flags)
561 flags = flags + ' ' + arch
562 _CONFIG_VARS[key] = flags
563
564 # If we're on OSX 10.5 or later and the user tries to
565 # compiles an extension using an SDK that is not present
566 # on the current machine it is better to not use an SDK
567 # than to fail.
568 #
569 # The major usecase for this is users using a Python.org
570 # binary installer on OSX 10.6: that installer uses
571 # the 10.4u SDK, but that SDK is not installed by default
572 # when you install Xcode.
573 #
574 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
575 m = re.search('-isysroot\s+(\S+)', CFLAGS)
576 if m is not None:
577 sdk = m.group(1)
578 if not os.path.exists(sdk):
579 for key in ('LDFLAGS', 'BASECFLAGS',
580 # a number of derived variables. These need to be
581 # patched up as well.
582 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
583
584 flags = _CONFIG_VARS[key]
585 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
586 _CONFIG_VARS[key] = flags
587
588 if args:
589 vals = []
590 for name in args:
591 vals.append(_CONFIG_VARS.get(name))
592 return vals
593 else:
594 return _CONFIG_VARS
595
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200596
Tarek Ziadéedacea32010-01-29 11:41:03 +0000597def get_config_var(name):
598 """Return the value of a single variable using the dictionary returned by
599 'get_config_vars()'.
600
601 Equivalent to get_config_vars().get(name)
602 """
603 return get_config_vars().get(name)
604
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200605
Tarek Ziadéedacea32010-01-29 11:41:03 +0000606def get_platform():
607 """Return a string that identifies the current platform.
608
609 This is used mainly to distinguish platform-specific build directories and
610 platform-specific built distributions. Typically includes the OS name
611 and version and the architecture (as supplied by 'os.uname()'),
612 although the exact information included depends on the OS; eg. for IRIX
613 the architecture isn't particularly important (IRIX only runs on SGI
614 hardware), but for Linux the kernel version isn't particularly
615 important.
616
617 Examples of returned values:
618 linux-i586
619 linux-alpha (?)
620 solaris-2.6-sun4u
621 irix-5.3
622 irix64-6.2
623
624 Windows will return one of:
625 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
626 win-ia64 (64bit Windows on Itanium)
627 win32 (all others - specifically, sys.platform is returned)
628
629 For other non-POSIX platforms, currently just returns 'sys.platform'.
630 """
Tarek Ziadéedacea32010-01-29 11:41:03 +0000631 if os.name == 'nt':
632 # sniff sys.version for architecture.
633 prefix = " bit ("
634 i = sys.version.find(prefix)
635 if i == -1:
636 return sys.platform
637 j = sys.version.find(")", i)
638 look = sys.version[i+len(prefix):j].lower()
639 if look == 'amd64':
640 return 'win-amd64'
641 if look == 'itanium':
642 return 'win-ia64'
643 return sys.platform
644
645 if os.name != "posix" or not hasattr(os, 'uname'):
646 # XXX what about the architecture? NT is Intel or Alpha,
647 # Mac OS is M68k or PPC, etc.
648 return sys.platform
649
650 # Try to distinguish various flavours of Unix
651 osname, host, release, version, machine = os.uname()
652
653 # Convert the OS name to lowercase, remove '/' characters
654 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
655 osname = osname.lower().replace('/', '')
656 machine = machine.replace(' ', '_')
657 machine = machine.replace('/', '-')
658
659 if osname[:5] == "linux":
660 # At least on Linux/Intel, 'machine' is the processor --
661 # i386, etc.
662 # XXX what about Alpha, SPARC, etc?
663 return "%s-%s" % (osname, machine)
664 elif osname[:5] == "sunos":
665 if release[0] >= "5": # SunOS 5 == Solaris 2
666 osname = "solaris"
667 release = "%d.%s" % (int(release[0]) - 3, release[2:])
Jesus Cea1aa1cf32012-01-18 04:49:26 +0100668 # We can't use "platform.architecture()[0]" because a
669 # bootstrap problem. We use a dict to get an error
670 # if some suspicious happens.
671 bitness = {2147483647:"32bit", 9223372036854775807:"64bit"}
Jesus Cea031605a2012-01-18 05:04:49 +0100672 machine += ".%s" % bitness[sys.maxsize]
Tarek Ziadéedacea32010-01-29 11:41:03 +0000673 # fall through to standard osname-release-machine representation
674 elif osname[:4] == "irix": # could be "irix64"!
675 return "%s-%s" % (osname, release)
676 elif osname[:3] == "aix":
677 return "%s-%s.%s" % (osname, version, release)
678 elif osname[:6] == "cygwin":
679 osname = "cygwin"
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200680 rel_re = re.compile(r'[\d.]+')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000681 m = rel_re.match(release)
682 if m:
683 release = m.group()
684 elif osname[:6] == "darwin":
685 #
686 # For our purposes, we'll assume that the system version from
687 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
688 # to. This makes the compatibility story a bit more sane because the
689 # machine is going to compile and link as if it were
690 # MACOSX_DEPLOYMENT_TARGET.
691 cfgvars = get_config_vars()
Ronald Oussoren222e89a2011-05-15 16:46:11 +0200692 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
Tarek Ziadéedacea32010-01-29 11:41:03 +0000693
Éric Araujo559b5f12011-05-25 18:21:43 +0200694 if True:
Tarek Ziadéedacea32010-01-29 11:41:03 +0000695 # Always calculate the release of the running machine,
696 # needed to determine if we can build fat binaries or not.
697
698 macrelease = macver
699 # Get the system version. Reading this plist is a documented
700 # way to get the system version (see the documentation for
701 # the Gestalt Manager)
702 try:
703 f = open('/System/Library/CoreServices/SystemVersion.plist')
704 except IOError:
705 # We're on a plain darwin box, fall back to the default
706 # behaviour.
707 pass
708 else:
Éric Araujobee5cef2010-11-05 23:51:56 +0000709 try:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200710 m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
711 r'<string>(.*?)</string>', f.read())
Éric Araujobee5cef2010-11-05 23:51:56 +0000712 finally:
713 f.close()
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200714 if m is not None:
715 macrelease = '.'.join(m.group(1).split('.')[:2])
716 # else: fall back to the default behaviour
Tarek Ziadéedacea32010-01-29 11:41:03 +0000717
718 if not macver:
719 macver = macrelease
720
721 if macver:
722 release = macver
723 osname = "macosx"
724
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200725 if ((macrelease + '.') >= '10.4.' and
726 '-arch' in get_config_vars().get('CFLAGS', '').strip()):
Tarek Ziadéedacea32010-01-29 11:41:03 +0000727 # The universal build will build fat binaries, but not on
728 # systems before 10.4
729 #
730 # Try to detect 4-way universal builds, those have machine-type
731 # 'universal' instead of 'fat'.
732
733 machine = 'fat'
734 cflags = get_config_vars().get('CFLAGS')
735
736 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussorend3950522010-07-11 09:05:07 +0000737 archs = tuple(sorted(set(archs)))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000738
739 if len(archs) == 1:
740 machine = archs[0]
741 elif archs == ('i386', 'ppc'):
742 machine = 'fat'
743 elif archs == ('i386', 'x86_64'):
744 machine = 'intel'
745 elif archs == ('i386', 'ppc', 'x86_64'):
746 machine = 'fat3'
747 elif archs == ('ppc64', 'x86_64'):
748 machine = 'fat64'
749 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
750 machine = 'universal'
751 else:
752 raise ValueError(
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200753 "Don't know machine value for archs=%r" % (archs,))
Tarek Ziadéedacea32010-01-29 11:41:03 +0000754
755 elif machine == 'i386':
756 # On OSX the machine type returned by uname is always the
757 # 32-bit variant, even if the executable architecture is
758 # the 64-bit variant
759 if sys.maxsize >= 2**32:
760 machine = 'x86_64'
761
762 elif machine in ('PowerPC', 'Power_Macintosh'):
763 # Pick a sane name for the PPC architecture.
764 # See 'i386' case
765 if sys.maxsize >= 2**32:
766 machine = 'ppc64'
767 else:
768 machine = 'ppc'
769
770 return "%s-%s-%s" % (osname, release, machine)
771
772
773def get_python_version():
774 return _PY_VERSION_SHORT
Tarek Ziadéa7514992010-05-25 09:44:36 +0000775
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200776
Tarek Ziadéa7514992010-05-25 09:44:36 +0000777def _print_dict(title, data):
778 for index, (key, value) in enumerate(sorted(data.items())):
779 if index == 0:
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200780 print('%s: ' % (title))
781 print('\t%s = "%s"' % (key, value))
782
Tarek Ziadéa7514992010-05-25 09:44:36 +0000783
784def _main():
Éric Araujo300623d2010-11-22 01:19:20 +0000785 """Display all information sysconfig detains."""
Antoine Pitrou1e73a242011-10-18 17:52:24 +0200786 if '--generate-posix-vars' in sys.argv:
787 _generate_posix_vars()
788 return
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200789 print('Platform: "%s"' % get_platform())
790 print('Python version: "%s"' % get_python_version())
791 print('Current installation scheme: "%s"' % _get_default_scheme())
Éric Araujo559b5f12011-05-25 18:21:43 +0200792 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000793 _print_dict('Paths', get_paths())
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200794 print()
Tarek Ziadéa7514992010-05-25 09:44:36 +0000795 _print_dict('Variables', get_config_vars())
796
Tarek Ziade1231a4e2011-05-19 13:07:25 +0200797
Tarek Ziadéa7514992010-05-25 09:44:36 +0000798if __name__ == '__main__':
799 _main()