blob: 77402d8ab7ef20a65cd2a2c5ed4bbf3758fc723b [file] [log] [blame]
Tarek Ziadé5633a802010-01-23 09:23:15 +00001"""Provide access to Python's configuration information.
2
3"""
4import sys
5import os
Florent Xicluna85677612010-03-10 23:58:42 +00006from os.path import pardir, realpath
Tarek Ziadé5633a802010-01-23 09:23:15 +00007
8_INSTALL_SCHEMES = {
9 'posix_prefix': {
10 'stdlib': '{base}/lib/python{py_version_short}',
11 'platstdlib': '{platbase}/lib/python{py_version_short}',
12 'purelib': '{base}/lib/python{py_version_short}/site-packages',
13 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
14 'include': '{base}/include/python{py_version_short}',
15 'platinclude': '{platbase}/include/python{py_version_short}',
16 'scripts': '{base}/bin',
17 'data': '{base}',
18 },
19 'posix_home': {
20 'stdlib': '{base}/lib/python',
21 'platstdlib': '{base}/lib/python',
22 'purelib': '{base}/lib/python',
23 'platlib': '{base}/lib/python',
24 'include': '{base}/include/python',
25 'platinclude': '{base}/include/python',
26 'scripts': '{base}/bin',
27 'data' : '{base}',
28 },
29 'nt': {
30 'stdlib': '{base}/Lib',
31 'platstdlib': '{base}/Lib',
32 'purelib': '{base}/Lib/site-packages',
33 'platlib': '{base}/Lib/site-packages',
34 'include': '{base}/Include',
35 'platinclude': '{base}/Include',
36 'scripts': '{base}/Scripts',
37 'data' : '{base}',
38 },
39 'os2': {
40 'stdlib': '{base}/Lib',
41 'platstdlib': '{base}/Lib',
42 'purelib': '{base}/Lib/site-packages',
43 'platlib': '{base}/Lib/site-packages',
44 'include': '{base}/Include',
45 'platinclude': '{base}/Include',
46 'scripts': '{base}/Scripts',
47 'data' : '{base}',
48 },
49 'os2_home': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000050 'stdlib': '{userbase}/lib/python{py_version_short}',
51 'platstdlib': '{userbase}/lib/python{py_version_short}',
52 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
53 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
Tarek Ziadé5633a802010-01-23 09:23:15 +000054 'include': '{userbase}/include/python{py_version_short}',
55 'scripts': '{userbase}/bin',
56 'data' : '{userbase}',
57 },
58 'nt_user': {
59 'stdlib': '{userbase}/Python{py_version_nodot}',
60 'platstdlib': '{userbase}/Python{py_version_nodot}',
61 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
62 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
63 'include': '{userbase}/Python{py_version_nodot}/Include',
64 'scripts': '{userbase}/Scripts',
65 'data' : '{userbase}',
66 },
67 'posix_user': {
Tarek Ziadé8f692272010-05-19 22:20:14 +000068 'stdlib': '{userbase}/lib/python{py_version_short}',
69 'platstdlib': '{userbase}/lib/python{py_version_short}',
70 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
71 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
Tarek Ziadé5633a802010-01-23 09:23:15 +000072 'include': '{userbase}/include/python{py_version_short}',
73 'scripts': '{userbase}/bin',
74 'data' : '{userbase}',
75 },
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +000076 'osx_framework_user': {
77 'stdlib': '{userbase}/lib/python',
78 'platstdlib': '{userbase}/lib/python',
79 'purelib': '{userbase}/lib/python/site-packages',
80 'platlib': '{userbase}/lib/python/site-packages',
81 'include': '{userbase}/include',
82 'scripts': '{userbase}/bin',
83 'data' : '{userbase}',
84 },
Tarek Ziadé5633a802010-01-23 09:23:15 +000085 }
86
87_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
88 'scripts', 'data')
89_PY_VERSION = sys.version.split()[0]
90_PY_VERSION_SHORT = sys.version[:3]
91_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
92_PREFIX = os.path.normpath(sys.prefix)
93_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
94_CONFIG_VARS = None
95_USER_BASE = None
Victor Stinnerd2f6ae62010-10-12 22:53:51 +000096
97def _safe_realpath(path):
98 try:
99 return realpath(path)
100 except OSError:
101 return path
102
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000103if sys.executable:
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000104 _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable))
Victor Stinner4a7e0c852010-03-11 12:34:39 +0000105else:
106 # sys.executable can be empty if argv[0] has been changed and Python is
107 # unable to retrieve the real program name
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000108 _PROJECT_BASE = _safe_realpath(os.getcwd())
Tarek Ziadé5633a802010-01-23 09:23:15 +0000109
110if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000111 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000112# PC/VS7.1
113if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000114 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000115# PC/AMD64
116if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower():
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000117 _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000118
119def is_python_build():
120 for fn in ("Setup.dist", "Setup.local"):
121 if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)):
122 return True
123 return False
124
125_PYTHON_BUILD = is_python_build()
126
127if _PYTHON_BUILD:
128 for scheme in ('posix_prefix', 'posix_home'):
129 _INSTALL_SCHEMES[scheme]['include'] = '{projectbase}/Include'
130 _INSTALL_SCHEMES[scheme]['platinclude'] = '{srcdir}'
131
132def _subst_vars(s, local_vars):
133 try:
134 return s.format(**local_vars)
135 except KeyError:
136 try:
137 return s.format(**os.environ)
138 except KeyError, var:
139 raise AttributeError('{%s}' % var)
140
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
148def _expand_vars(scheme, vars):
149 res = {}
150 if vars is None:
151 vars = {}
152 _extend_dict(vars, get_config_vars())
153
154 for key, value in _INSTALL_SCHEMES[scheme].items():
155 if os.name in ('posix', 'nt'):
156 value = os.path.expanduser(value)
157 res[key] = os.path.normpath(_subst_vars(value, vars))
158 return res
159
160def _get_default_scheme():
161 if os.name == 'posix':
162 # the default scheme for posix is posix_prefix
163 return 'posix_prefix'
164 return os.name
165
166def _getuserbase():
167 env_base = os.environ.get("PYTHONUSERBASE", None)
168 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 "~"
174 return env_base if env_base else joinuser(base, "Python")
175
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000176 if sys.platform == "darwin":
177 framework = get_config_var("PYTHONFRAMEWORK")
178 if framework:
179 return joinuser("~", "Library", framework, "%d.%d"%(
180 sys.version_info[:2]))
181
Tarek Ziadé5633a802010-01-23 09:23:15 +0000182 return env_base if env_base else joinuser("~", ".local")
183
184
185def _parse_makefile(filename, vars=None):
186 """Parse a Makefile-style file.
187
188 A dictionary containing name/value pairs is returned. If an
189 optional dictionary is passed in as the second argument, it is
190 used instead of a new dictionary.
191 """
192 import re
193 # Regexes needed for parsing Makefile (and similar syntaxes,
194 # like old-style Setup files).
195 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
196 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
197 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
198
199 if vars is None:
200 vars = {}
201 done = {}
202 notdone = {}
203
204 with open(filename) as f:
205 lines = f.readlines()
206
207 for line in lines:
208 if line.startswith('#') or line.strip() == '':
209 continue
210 m = _variable_rx.match(line)
211 if m:
212 n, v = m.group(1, 2)
213 v = v.strip()
214 # `$$' is a literal `$' in make
215 tmpv = v.replace('$$', '')
216
217 if "$" in tmpv:
218 notdone[n] = v
219 else:
220 try:
221 v = int(v)
222 except ValueError:
223 # insert literal `$'
224 done[n] = v.replace('$$', '$')
225 else:
226 done[n] = v
227
228 # do variable interpolation here
229 while notdone:
230 for name in notdone.keys():
231 value = notdone[name]
232 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
233 if m:
234 n = m.group(1)
235 found = True
236 if n in done:
237 item = str(done[n])
238 elif n in notdone:
239 # get it on a subsequent round
240 found = False
241 elif n in os.environ:
242 # do it like make: fall back to environment
243 item = os.environ[n]
244 else:
245 done[n] = item = ""
246 if found:
247 after = value[m.end():]
248 value = value[:m.start()] + item + after
249 if "$" in after:
250 notdone[name] = value
251 else:
252 try: value = int(value)
253 except ValueError:
254 done[name] = value.strip()
255 else:
256 done[name] = value
257 del notdone[name]
258 else:
259 # bogus variable reference; just drop it since we can't deal
260 del notdone[name]
Antoine Pitrou58dab672010-10-10 09:54:59 +0000261 # strip spurious spaces
262 for k, v in done.items():
263 if isinstance(v, str):
264 done[k] = v.strip()
265
Tarek Ziadé5633a802010-01-23 09:23:15 +0000266 # save the results in the global dictionary
267 vars.update(done)
268 return vars
269
Tarek Ziadé5633a802010-01-23 09:23:15 +0000270
271def _get_makefile_filename():
272 if _PYTHON_BUILD:
273 return os.path.join(_PROJECT_BASE, "Makefile")
Barry Warsaw42bb7ca2011-02-14 20:04:00 +0000274 return os.path.join(get_path('platstdlib'), "config", "Makefile")
Tarek Ziadé5633a802010-01-23 09:23:15 +0000275
Tarek Ziadé5633a802010-01-23 09:23:15 +0000276
277def _init_posix(vars):
278 """Initialize the module as appropriate for POSIX systems."""
279 # load the installed Makefile:
280 makefile = _get_makefile_filename()
281 try:
282 _parse_makefile(makefile, vars)
283 except IOError, e:
284 msg = "invalid Python installation: unable to open %s" % makefile
285 if hasattr(e, "strerror"):
286 msg = msg + " (%s)" % e.strerror
287 raise IOError(msg)
288
289 # load the installed pyconfig.h:
290 config_h = get_config_h_filename()
291 try:
Antoine Pitrouf7c24452010-10-14 21:22:52 +0000292 with open(config_h) as f:
293 parse_config_h(f, vars)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000294 except IOError, e:
295 msg = "invalid Python installation: unable to open %s" % config_h
296 if hasattr(e, "strerror"):
297 msg = msg + " (%s)" % e.strerror
298 raise IOError(msg)
299
300 # On MacOSX we need to check the setting of the environment variable
301 # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
302 # it needs to be compatible.
303 # If it isn't set we set it to the configure-time value
304 if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in vars:
305 cfg_target = vars['MACOSX_DEPLOYMENT_TARGET']
306 cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
307 if cur_target == '':
308 cur_target = cfg_target
309 os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
310 elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')):
311 msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" '
312 'during configure' % (cur_target, cfg_target))
313 raise IOError(msg)
314
315 # On AIX, there are wrong paths to the linker scripts in the Makefile
316 # -- these paths are relative to the Python source, but when installed
317 # the scripts are in another directory.
318 if _PYTHON_BUILD:
319 vars['LDSHARED'] = vars['BLDSHARED']
320
321def _init_non_posix(vars):
322 """Initialize the module as appropriate for NT"""
323 # set basic install directories
324 vars['LIBDEST'] = get_path('stdlib')
325 vars['BINLIBDEST'] = get_path('platstdlib')
326 vars['INCLUDEPY'] = get_path('include')
327 vars['SO'] = '.pyd'
328 vars['EXE'] = '.exe'
329 vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000330 vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000331
332#
333# public APIs
334#
335
Tarek Ziadécc118172010-02-02 22:50:23 +0000336
337def parse_config_h(fp, vars=None):
338 """Parse a config.h-style file.
339
340 A dictionary containing name/value pairs is returned. If an
341 optional dictionary is passed in as the second argument, it is
342 used instead of a new dictionary.
343 """
344 import re
345 if vars is None:
346 vars = {}
347 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
348 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
349
350 while True:
351 line = fp.readline()
352 if not line:
353 break
354 m = define_rx.match(line)
355 if m:
356 n, v = m.group(1, 2)
357 try: v = int(v)
358 except ValueError: pass
359 vars[n] = v
360 else:
361 m = undef_rx.match(line)
362 if m:
363 vars[m.group(1)] = 0
364 return vars
365
366def get_config_h_filename():
367 """Returns the path of pyconfig.h."""
368 if _PYTHON_BUILD:
369 if os.name == "nt":
370 inc_dir = os.path.join(_PROJECT_BASE, "PC")
371 else:
372 inc_dir = _PROJECT_BASE
373 else:
374 inc_dir = get_path('platinclude')
375 return os.path.join(inc_dir, 'pyconfig.h')
376
Tarek Ziadé5633a802010-01-23 09:23:15 +0000377def get_scheme_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000378 """Returns a tuple containing the schemes names."""
Tarek Ziadée81b0282010-02-02 22:54:28 +0000379 schemes = _INSTALL_SCHEMES.keys()
380 schemes.sort()
381 return tuple(schemes)
Tarek Ziadé5633a802010-01-23 09:23:15 +0000382
383def get_path_names():
Tarek Ziadécc118172010-02-02 22:50:23 +0000384 """Returns a tuple containing the paths names."""
Tarek Ziadé5633a802010-01-23 09:23:15 +0000385 return _SCHEME_KEYS
386
387def get_paths(scheme=_get_default_scheme(), vars=None, expand=True):
388 """Returns a mapping containing an install scheme.
389
390 ``scheme`` is the install scheme name. If not provided, it will
391 return the default scheme for the current platform.
392 """
393 if expand:
394 return _expand_vars(scheme, vars)
395 else:
396 return _INSTALL_SCHEMES[scheme]
397
398def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True):
399 """Returns a path corresponding to the scheme.
400
401 ``scheme`` is the install scheme name.
402 """
403 return get_paths(scheme, vars, expand)[name]
404
405def get_config_vars(*args):
406 """With no arguments, return a dictionary of all configuration
407 variables relevant for the current platform.
408
409 On Unix, this means every variable defined in Python's installed Makefile;
410 On Windows and Mac OS it's a much smaller set.
411
412 With arguments, return a list of values that result from looking up
413 each argument in the configuration variable dictionary.
414 """
415 import re
416 global _CONFIG_VARS
417 if _CONFIG_VARS is None:
418 _CONFIG_VARS = {}
419 # Normalized versions of prefix and exec_prefix are handy to have;
420 # in fact, these are the standard versions used most places in the
421 # Distutils.
422 _CONFIG_VARS['prefix'] = _PREFIX
423 _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX
424 _CONFIG_VARS['py_version'] = _PY_VERSION
425 _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
426 _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2]
427 _CONFIG_VARS['base'] = _PREFIX
428 _CONFIG_VARS['platbase'] = _EXEC_PREFIX
Tarek Ziadé5633a802010-01-23 09:23:15 +0000429 _CONFIG_VARS['projectbase'] = _PROJECT_BASE
430
431 if os.name in ('nt', 'os2'):
432 _init_non_posix(_CONFIG_VARS)
433 if os.name == 'posix':
434 _init_posix(_CONFIG_VARS)
435
Ronald Oussoren2f88bfd2010-05-08 10:29:06 +0000436 # Setting 'userbase' is done below the call to the
437 # init function to enable using 'get_config_var' in
438 # the init-function.
439 _CONFIG_VARS['userbase'] = _getuserbase()
440
Tarek Ziadé5633a802010-01-23 09:23:15 +0000441 if 'srcdir' not in _CONFIG_VARS:
442 _CONFIG_VARS['srcdir'] = _PROJECT_BASE
443
444 # Convert srcdir into an absolute path if it appears necessary.
445 # Normally it is relative to the build directory. However, during
446 # testing, for example, we might be running a non-installed python
447 # from a different directory.
448 if _PYTHON_BUILD and os.name == "posix":
449 base = _PROJECT_BASE
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000450 try:
451 cwd = os.getcwd()
452 except OSError:
453 cwd = None
Tarek Ziadé5633a802010-01-23 09:23:15 +0000454 if (not os.path.isabs(_CONFIG_VARS['srcdir']) and
Victor Stinnerd2f6ae62010-10-12 22:53:51 +0000455 base != cwd):
Tarek Ziadé5633a802010-01-23 09:23:15 +0000456 # srcdir is relative and we are not in the same directory
457 # as the executable. Assume executable is in the build
458 # directory and make srcdir absolute.
459 srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
460 _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
461
462 if sys.platform == 'darwin':
463 kernel_version = os.uname()[2] # Kernel version (8.4.3)
464 major_version = int(kernel_version.split('.')[0])
465
466 if major_version < 8:
467 # On Mac OS X before 10.4, check if -arch and -isysroot
468 # are in CFLAGS or LDFLAGS and remove them if they are.
469 # This is needed when building extensions on a 10.3 system
470 # using a universal build of python.
471 for key in ('LDFLAGS', 'BASECFLAGS',
472 # a number of derived variables. These need to be
473 # patched up as well.
474 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
475 flags = _CONFIG_VARS[key]
476 flags = re.sub('-arch\s+\w+\s', ' ', flags)
477 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
478 _CONFIG_VARS[key] = flags
479 else:
480 # Allow the user to override the architecture flags using
481 # an environment variable.
482 # NOTE: This name was introduced by Apple in OSX 10.5 and
483 # is used by several scripting languages distributed with
484 # that OS release.
485 if 'ARCHFLAGS' in os.environ:
486 arch = os.environ['ARCHFLAGS']
487 for key in ('LDFLAGS', 'BASECFLAGS',
488 # a number of derived variables. These need to be
489 # patched up as well.
490 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
491
492 flags = _CONFIG_VARS[key]
493 flags = re.sub('-arch\s+\w+\s', ' ', flags)
494 flags = flags + ' ' + arch
495 _CONFIG_VARS[key] = flags
496
497 # If we're on OSX 10.5 or later and the user tries to
498 # compiles an extension using an SDK that is not present
499 # on the current machine it is better to not use an SDK
500 # than to fail.
501 #
502 # The major usecase for this is users using a Python.org
503 # binary installer on OSX 10.6: that installer uses
504 # the 10.4u SDK, but that SDK is not installed by default
505 # when you install Xcode.
506 #
507 CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
508 m = re.search('-isysroot\s+(\S+)', CFLAGS)
509 if m is not None:
510 sdk = m.group(1)
511 if not os.path.exists(sdk):
512 for key in ('LDFLAGS', 'BASECFLAGS',
513 # a number of derived variables. These need to be
514 # patched up as well.
515 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
516
517 flags = _CONFIG_VARS[key]
518 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
519 _CONFIG_VARS[key] = flags
520
521 if args:
522 vals = []
523 for name in args:
524 vals.append(_CONFIG_VARS.get(name))
525 return vals
526 else:
527 return _CONFIG_VARS
528
529def get_config_var(name):
530 """Return the value of a single variable using the dictionary returned by
531 'get_config_vars()'.
532
533 Equivalent to get_config_vars().get(name)
534 """
535 return get_config_vars().get(name)
536
537def get_platform():
538 """Return a string that identifies the current platform.
539
540 This is used mainly to distinguish platform-specific build directories and
541 platform-specific built distributions. Typically includes the OS name
542 and version and the architecture (as supplied by 'os.uname()'),
543 although the exact information included depends on the OS; eg. for IRIX
544 the architecture isn't particularly important (IRIX only runs on SGI
545 hardware), but for Linux the kernel version isn't particularly
546 important.
547
548 Examples of returned values:
549 linux-i586
550 linux-alpha (?)
551 solaris-2.6-sun4u
552 irix-5.3
553 irix64-6.2
554
555 Windows will return one of:
556 win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
557 win-ia64 (64bit Windows on Itanium)
558 win32 (all others - specifically, sys.platform is returned)
559
560 For other non-POSIX platforms, currently just returns 'sys.platform'.
561 """
562 import re
563 if os.name == 'nt':
564 # sniff sys.version for architecture.
565 prefix = " bit ("
566 i = sys.version.find(prefix)
567 if i == -1:
568 return sys.platform
569 j = sys.version.find(")", i)
570 look = sys.version[i+len(prefix):j].lower()
571 if look == 'amd64':
572 return 'win-amd64'
573 if look == 'itanium':
574 return 'win-ia64'
575 return sys.platform
576
577 if os.name != "posix" or not hasattr(os, 'uname'):
578 # XXX what about the architecture? NT is Intel or Alpha,
579 # Mac OS is M68k or PPC, etc.
580 return sys.platform
581
582 # Try to distinguish various flavours of Unix
583 osname, host, release, version, machine = os.uname()
584
585 # Convert the OS name to lowercase, remove '/' characters
586 # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh")
587 osname = osname.lower().replace('/', '')
588 machine = machine.replace(' ', '_')
589 machine = machine.replace('/', '-')
590
591 if osname[:5] == "linux":
592 # At least on Linux/Intel, 'machine' is the processor --
593 # i386, etc.
594 # XXX what about Alpha, SPARC, etc?
595 return "%s-%s" % (osname, machine)
596 elif osname[:5] == "sunos":
597 if release[0] >= "5": # SunOS 5 == Solaris 2
598 osname = "solaris"
599 release = "%d.%s" % (int(release[0]) - 3, release[2:])
600 # fall through to standard osname-release-machine representation
601 elif osname[:4] == "irix": # could be "irix64"!
602 return "%s-%s" % (osname, release)
603 elif osname[:3] == "aix":
604 return "%s-%s.%s" % (osname, version, release)
605 elif osname[:6] == "cygwin":
606 osname = "cygwin"
607 rel_re = re.compile (r'[\d.]+')
608 m = rel_re.match(release)
609 if m:
610 release = m.group()
611 elif osname[:6] == "darwin":
612 #
613 # For our purposes, we'll assume that the system version from
614 # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
615 # to. This makes the compatibility story a bit more sane because the
616 # machine is going to compile and link as if it were
617 # MACOSX_DEPLOYMENT_TARGET.
618 cfgvars = get_config_vars()
619 macver = os.environ.get('MACOSX_DEPLOYMENT_TARGET')
620 if not macver:
621 macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
622
623 if 1:
624 # Always calculate the release of the running machine,
625 # needed to determine if we can build fat binaries or not.
626
627 macrelease = macver
628 # Get the system version. Reading this plist is a documented
629 # way to get the system version (see the documentation for
630 # the Gestalt Manager)
631 try:
632 f = open('/System/Library/CoreServices/SystemVersion.plist')
633 except IOError:
634 # We're on a plain darwin box, fall back to the default
635 # behaviour.
636 pass
637 else:
Éric Araujod1feff72010-11-06 04:06:18 +0000638 try:
639 m = re.search(
640 r'<key>ProductUserVisibleVersion</key>\s*' +
641 r'<string>(.*?)</string>', f.read())
642 f.close()
643 if m is not None:
644 macrelease = '.'.join(m.group(1).split('.')[:2])
645 # else: fall back to the default behaviour
646 finally:
647 f.close()
Tarek Ziadé5633a802010-01-23 09:23:15 +0000648
649 if not macver:
650 macver = macrelease
651
652 if macver:
653 release = macver
654 osname = "macosx"
655
656 if (macrelease + '.') >= '10.4.' and \
657 '-arch' in get_config_vars().get('CFLAGS', '').strip():
658 # The universal build will build fat binaries, but not on
659 # systems before 10.4
660 #
661 # Try to detect 4-way universal builds, those have machine-type
662 # 'universal' instead of 'fat'.
663
664 machine = 'fat'
665 cflags = get_config_vars().get('CFLAGS')
666
667 archs = re.findall('-arch\s+(\S+)', cflags)
Ronald Oussoren75956202010-07-11 08:52:52 +0000668 archs = tuple(sorted(set(archs)))
Tarek Ziadé5633a802010-01-23 09:23:15 +0000669
670 if len(archs) == 1:
671 machine = archs[0]
672 elif archs == ('i386', 'ppc'):
673 machine = 'fat'
674 elif archs == ('i386', 'x86_64'):
675 machine = 'intel'
676 elif archs == ('i386', 'ppc', 'x86_64'):
677 machine = 'fat3'
678 elif archs == ('ppc64', 'x86_64'):
679 machine = 'fat64'
680 elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
681 machine = 'universal'
682 else:
683 raise ValueError(
684 "Don't know machine value for archs=%r"%(archs,))
685
686 elif machine == 'i386':
687 # On OSX the machine type returned by uname is always the
688 # 32-bit variant, even if the executable architecture is
689 # the 64-bit variant
690 if sys.maxint >= 2**32:
691 machine = 'x86_64'
692
693 elif machine in ('PowerPC', 'Power_Macintosh'):
694 # Pick a sane name for the PPC architecture.
695 # See 'i386' case
696 if sys.maxint >= 2**32:
697 machine = 'ppc64'
698 else:
699 machine = 'ppc'
700
701 return "%s-%s-%s" % (osname, release, machine)
702
703
704def get_python_version():
705 return _PY_VERSION_SHORT