Some platforms have rl_completion_append_character but not rl_completion_suppress_append.
[python.git] / Lib / distutils / sysconfig.py
blob6ca6720adbe519ba5d35d42f32562d45f42855c5
1 """Provide access to Python's configuration information. The specific
2 configuration variables available depend heavily on the platform and
3 configuration. The values may be retrieved using
4 get_config_var(name), and the list of variables is available via
5 get_config_vars().keys(). Additional convenience functions are also
6 available.
8 Written by: Fred L. Drake, Jr.
9 Email: <fdrake@acm.org>
10 """
12 __revision__ = "$Id$"
14 import os
15 import re
16 import sys
18 from distutils.errors import DistutilsPlatformError
20 # These are needed in a couple of spots, so just compute them once.
21 PREFIX = os.path.normpath(sys.prefix)
22 EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
24 # Path to the base directory of the project. On Windows the binary may
25 # live in project/PCBuild9. If we're dealing with an x64 Windows build,
26 # it'll live in project/PCbuild/amd64.
27 project_base = os.path.dirname(os.path.abspath(sys.executable))
28 if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
29 project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
30 # PC/VS7.1
31 if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
32 project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
33 os.path.pardir))
34 # PC/AMD64
35 if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower():
36 project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
37 os.path.pardir))
39 # python_build: (Boolean) if true, we're either building Python or
40 # building an extension with an un-installed Python, so we use
41 # different (hard-wired) directories.
42 # Setup.local is available for Makefile builds including VPATH builds,
43 # Setup.dist is available on Windows
44 def _python_build():
45 for fn in ("Setup.dist", "Setup.local"):
46 if os.path.isfile(os.path.join(project_base, "Modules", fn)):
47 return True
48 return False
49 python_build = _python_build()
52 def get_python_version():
53 """Return a string containing the major and minor Python version,
54 leaving off the patchlevel. Sample return values could be '1.5'
55 or '2.2'.
56 """
57 return sys.version[:3]
60 def get_python_inc(plat_specific=0, prefix=None):
61 """Return the directory containing installed Python header files.
63 If 'plat_specific' is false (the default), this is the path to the
64 non-platform-specific header files, i.e. Python.h and so on;
65 otherwise, this is the path to platform-specific header files
66 (namely pyconfig.h).
68 If 'prefix' is supplied, use it instead of sys.prefix or
69 sys.exec_prefix -- i.e., ignore 'plat_specific'.
70 """
71 if prefix is None:
72 prefix = plat_specific and EXEC_PREFIX or PREFIX
73 if os.name == "posix":
74 if python_build:
75 # Assume the executable is in the build directory. The
76 # pyconfig.h file should be in the same directory. Since
77 # the build directory may not be the source directory, we
78 # must use "srcdir" from the makefile to find the "Include"
79 # directory.
80 base = os.path.dirname(os.path.abspath(sys.executable))
81 if plat_specific:
82 return base
83 else:
84 incdir = os.path.join(get_config_var('srcdir'), 'Include')
85 return os.path.normpath(incdir)
86 return os.path.join(prefix, "include", "python" + get_python_version())
87 elif os.name == "nt":
88 return os.path.join(prefix, "include")
89 elif os.name == "mac":
90 if plat_specific:
91 return os.path.join(prefix, "Mac", "Include")
92 else:
93 return os.path.join(prefix, "Include")
94 elif os.name == "os2":
95 return os.path.join(prefix, "Include")
96 else:
97 raise DistutilsPlatformError(
98 "I don't know where Python installs its C header files "
99 "on platform '%s'" % os.name)
102 def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
103 """Return the directory containing the Python library (standard or
104 site additions).
106 If 'plat_specific' is true, return the directory containing
107 platform-specific modules, i.e. any module from a non-pure-Python
108 module distribution; otherwise, return the platform-shared library
109 directory. If 'standard_lib' is true, return the directory
110 containing standard Python library modules; otherwise, return the
111 directory for site-specific modules.
113 If 'prefix' is supplied, use it instead of sys.prefix or
114 sys.exec_prefix -- i.e., ignore 'plat_specific'.
116 if prefix is None:
117 prefix = plat_specific and EXEC_PREFIX or PREFIX
119 if os.name == "posix":
120 libpython = os.path.join(prefix,
121 "lib", "python" + get_python_version())
122 if standard_lib:
123 return libpython
124 else:
125 return os.path.join(libpython, "site-packages")
127 elif os.name == "nt":
128 if standard_lib:
129 return os.path.join(prefix, "Lib")
130 else:
131 if get_python_version() < "2.2":
132 return prefix
133 else:
134 return os.path.join(prefix, "Lib", "site-packages")
136 elif os.name == "mac":
137 if plat_specific:
138 if standard_lib:
139 return os.path.join(prefix, "Lib", "lib-dynload")
140 else:
141 return os.path.join(prefix, "Lib", "site-packages")
142 else:
143 if standard_lib:
144 return os.path.join(prefix, "Lib")
145 else:
146 return os.path.join(prefix, "Lib", "site-packages")
148 elif os.name == "os2":
149 if standard_lib:
150 return os.path.join(prefix, "Lib")
151 else:
152 return os.path.join(prefix, "Lib", "site-packages")
154 else:
155 raise DistutilsPlatformError(
156 "I don't know where Python installs its library "
157 "on platform '%s'" % os.name)
160 def customize_compiler(compiler):
161 """Do any platform-specific customization of a CCompiler instance.
163 Mainly needed on Unix, so we can plug in the information that
164 varies across Unices and is stored in Python's Makefile.
166 if compiler.compiler_type == "unix":
167 (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
168 get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
169 'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
171 if 'CC' in os.environ:
172 cc = os.environ['CC']
173 if 'CXX' in os.environ:
174 cxx = os.environ['CXX']
175 if 'LDSHARED' in os.environ:
176 ldshared = os.environ['LDSHARED']
177 if 'CPP' in os.environ:
178 cpp = os.environ['CPP']
179 else:
180 cpp = cc + " -E" # not always
181 if 'LDFLAGS' in os.environ:
182 ldshared = ldshared + ' ' + os.environ['LDFLAGS']
183 if 'CFLAGS' in os.environ:
184 cflags = opt + ' ' + os.environ['CFLAGS']
185 ldshared = ldshared + ' ' + os.environ['CFLAGS']
186 if 'CPPFLAGS' in os.environ:
187 cpp = cpp + ' ' + os.environ['CPPFLAGS']
188 cflags = cflags + ' ' + os.environ['CPPFLAGS']
189 ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
190 if 'AR' in os.environ:
191 ar = os.environ['AR']
192 if 'ARFLAGS' in os.environ:
193 archiver = ar + ' ' + os.environ['ARFLAGS']
194 else:
195 archiver = ar + ' ' + ar_flags
197 cc_cmd = cc + ' ' + cflags
198 compiler.set_executables(
199 preprocessor=cpp,
200 compiler=cc_cmd,
201 compiler_so=cc_cmd + ' ' + ccshared,
202 compiler_cxx=cxx,
203 linker_so=ldshared,
204 linker_exe=cc,
205 archiver=archiver)
207 compiler.shared_lib_extension = so_ext
210 def get_config_h_filename():
211 """Return full pathname of installed pyconfig.h file."""
212 if python_build:
213 if os.name == "nt":
214 inc_dir = os.path.join(project_base, "PC")
215 else:
216 inc_dir = project_base
217 else:
218 inc_dir = get_python_inc(plat_specific=1)
219 if get_python_version() < '2.2':
220 config_h = 'config.h'
221 else:
222 # The name of the config.h file changed in 2.2
223 config_h = 'pyconfig.h'
224 return os.path.join(inc_dir, config_h)
227 def get_makefile_filename():
228 """Return full pathname of installed Makefile from the Python build."""
229 if python_build:
230 return os.path.join(os.path.dirname(sys.executable), "Makefile")
231 lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
232 return os.path.join(lib_dir, "config", "Makefile")
235 def parse_config_h(fp, g=None):
236 """Parse a config.h-style file.
238 A dictionary containing name/value pairs is returned. If an
239 optional dictionary is passed in as the second argument, it is
240 used instead of a new dictionary.
242 if g is None:
243 g = {}
244 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
245 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
247 while 1:
248 line = fp.readline()
249 if not line:
250 break
251 m = define_rx.match(line)
252 if m:
253 n, v = m.group(1, 2)
254 try: v = int(v)
255 except ValueError: pass
256 g[n] = v
257 else:
258 m = undef_rx.match(line)
259 if m:
260 g[m.group(1)] = 0
261 return g
264 # Regexes needed for parsing Makefile (and similar syntaxes,
265 # like old-style Setup files).
266 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
267 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
268 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
270 def parse_makefile(fn, g=None):
271 """Parse a Makefile-style file.
273 A dictionary containing name/value pairs is returned. If an
274 optional dictionary is passed in as the second argument, it is
275 used instead of a new dictionary.
277 from distutils.text_file import TextFile
278 fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
280 if g is None:
281 g = {}
282 done = {}
283 notdone = {}
285 while 1:
286 line = fp.readline()
287 if line is None: # eof
288 break
289 m = _variable_rx.match(line)
290 if m:
291 n, v = m.group(1, 2)
292 v = v.strip()
293 # `$$' is a literal `$' in make
294 tmpv = v.replace('$$', '')
296 if "$" in tmpv:
297 notdone[n] = v
298 else:
299 try:
300 v = int(v)
301 except ValueError:
302 # insert literal `$'
303 done[n] = v.replace('$$', '$')
304 else:
305 done[n] = v
307 # do variable interpolation here
308 while notdone:
309 for name in notdone.keys():
310 value = notdone[name]
311 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
312 if m:
313 n = m.group(1)
314 found = True
315 if n in done:
316 item = str(done[n])
317 elif n in notdone:
318 # get it on a subsequent round
319 found = False
320 elif n in os.environ:
321 # do it like make: fall back to environment
322 item = os.environ[n]
323 else:
324 done[n] = item = ""
325 if found:
326 after = value[m.end():]
327 value = value[:m.start()] + item + after
328 if "$" in after:
329 notdone[name] = value
330 else:
331 try: value = int(value)
332 except ValueError:
333 done[name] = value.strip()
334 else:
335 done[name] = value
336 del notdone[name]
337 else:
338 # bogus variable reference; just drop it since we can't deal
339 del notdone[name]
341 fp.close()
343 # save the results in the global dictionary
344 g.update(done)
345 return g
348 def expand_makefile_vars(s, vars):
349 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
350 'string' according to 'vars' (a dictionary mapping variable names to
351 values). Variables not present in 'vars' are silently expanded to the
352 empty string. The variable values in 'vars' should not contain further
353 variable expansions; if 'vars' is the output of 'parse_makefile()',
354 you're fine. Returns a variable-expanded version of 's'.
357 # This algorithm does multiple expansion, so if vars['foo'] contains
358 # "${bar}", it will expand ${foo} to ${bar}, and then expand
359 # ${bar}... and so forth. This is fine as long as 'vars' comes from
360 # 'parse_makefile()', which takes care of such expansions eagerly,
361 # according to make's variable expansion semantics.
363 while 1:
364 m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
365 if m:
366 (beg, end) = m.span()
367 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
368 else:
369 break
370 return s
373 _config_vars = None
375 def _init_posix():
376 """Initialize the module as appropriate for POSIX systems."""
377 g = {}
378 # load the installed Makefile:
379 try:
380 filename = get_makefile_filename()
381 parse_makefile(filename, g)
382 except IOError, msg:
383 my_msg = "invalid Python installation: unable to open %s" % filename
384 if hasattr(msg, "strerror"):
385 my_msg = my_msg + " (%s)" % msg.strerror
387 raise DistutilsPlatformError(my_msg)
389 # load the installed pyconfig.h:
390 try:
391 filename = get_config_h_filename()
392 parse_config_h(file(filename), g)
393 except IOError, msg:
394 my_msg = "invalid Python installation: unable to open %s" % filename
395 if hasattr(msg, "strerror"):
396 my_msg = my_msg + " (%s)" % msg.strerror
398 raise DistutilsPlatformError(my_msg)
400 # On MacOSX we need to check the setting of the environment variable
401 # MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
402 # it needs to be compatible.
403 # If it isn't set we set it to the configure-time value
404 if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g:
405 cfg_target = g['MACOSX_DEPLOYMENT_TARGET']
406 cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
407 if cur_target == '':
408 cur_target = cfg_target
409 os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
410 elif map(int, cfg_target.split('.')) > map(int, cur_target.split('.')):
411 my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure'
412 % (cur_target, cfg_target))
413 raise DistutilsPlatformError(my_msg)
415 # On AIX, there are wrong paths to the linker scripts in the Makefile
416 # -- these paths are relative to the Python source, but when installed
417 # the scripts are in another directory.
418 if python_build:
419 g['LDSHARED'] = g['BLDSHARED']
421 elif get_python_version() < '2.1':
422 # The following two branches are for 1.5.2 compatibility.
423 if sys.platform == 'aix4': # what about AIX 3.x ?
424 # Linker script is in the config directory, not in Modules as the
425 # Makefile says.
426 python_lib = get_python_lib(standard_lib=1)
427 ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
428 python_exp = os.path.join(python_lib, 'config', 'python.exp')
430 g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
432 elif sys.platform == 'beos':
433 # Linker script is in the config directory. In the Makefile it is
434 # relative to the srcdir, which after installation no longer makes
435 # sense.
436 python_lib = get_python_lib(standard_lib=1)
437 linkerscript_path = g['LDSHARED'].split()[0]
438 linkerscript_name = os.path.basename(linkerscript_path)
439 linkerscript = os.path.join(python_lib, 'config',
440 linkerscript_name)
442 # XXX this isn't the right place to do this: adding the Python
443 # library to the link, if needed, should be in the "build_ext"
444 # command. (It's also needed for non-MS compilers on Windows, and
445 # it's taken care of for them by the 'build_ext.get_libraries()'
446 # method.)
447 g['LDSHARED'] = ("%s -L%s/lib -lpython%s" %
448 (linkerscript, PREFIX, get_python_version()))
450 global _config_vars
451 _config_vars = g
454 def _init_nt():
455 """Initialize the module as appropriate for NT"""
456 g = {}
457 # set basic install directories
458 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
459 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
461 # XXX hmmm.. a normal install puts include files here
462 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
464 g['SO'] = '.pyd'
465 g['EXE'] = ".exe"
466 g['VERSION'] = get_python_version().replace(".", "")
467 g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
469 global _config_vars
470 _config_vars = g
473 def _init_mac():
474 """Initialize the module as appropriate for Macintosh systems"""
475 g = {}
476 # set basic install directories
477 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
478 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
480 # XXX hmmm.. a normal install puts include files here
481 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
483 import MacOS
484 if not hasattr(MacOS, 'runtimemodel'):
485 g['SO'] = '.ppc.slb'
486 else:
487 g['SO'] = '.%s.slb' % MacOS.runtimemodel
489 # XXX are these used anywhere?
490 g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
491 g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
493 # These are used by the extension module build
494 g['srcdir'] = ':'
495 global _config_vars
496 _config_vars = g
499 def _init_os2():
500 """Initialize the module as appropriate for OS/2"""
501 g = {}
502 # set basic install directories
503 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
504 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
506 # XXX hmmm.. a normal install puts include files here
507 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
509 g['SO'] = '.pyd'
510 g['EXE'] = ".exe"
512 global _config_vars
513 _config_vars = g
516 def get_config_vars(*args):
517 """With no arguments, return a dictionary of all configuration
518 variables relevant for the current platform. Generally this includes
519 everything needed to build extensions and install both pure modules and
520 extensions. On Unix, this means every variable defined in Python's
521 installed Makefile; on Windows and Mac OS it's a much smaller set.
523 With arguments, return a list of values that result from looking up
524 each argument in the configuration variable dictionary.
526 global _config_vars
527 if _config_vars is None:
528 func = globals().get("_init_" + os.name)
529 if func:
530 func()
531 else:
532 _config_vars = {}
534 # Normalized versions of prefix and exec_prefix are handy to have;
535 # in fact, these are the standard versions used most places in the
536 # Distutils.
537 _config_vars['prefix'] = PREFIX
538 _config_vars['exec_prefix'] = EXEC_PREFIX
540 if 'srcdir' not in _config_vars:
541 _config_vars['srcdir'] = project_base
543 # Convert srcdir into an absolute path if it appears necessary.
544 # Normally it is relative to the build directory. However, during
545 # testing, for example, we might be running a non-installed python
546 # from a different directory.
547 if python_build and os.name == "posix":
548 base = os.path.dirname(os.path.abspath(sys.executable))
549 if (not os.path.isabs(_config_vars['srcdir']) and
550 base != os.getcwd()):
551 # srcdir is relative and we are not in the same directory
552 # as the executable. Assume executable is in the build
553 # directory and make srcdir absolute.
554 srcdir = os.path.join(base, _config_vars['srcdir'])
555 _config_vars['srcdir'] = os.path.normpath(srcdir)
557 if sys.platform == 'darwin':
558 kernel_version = os.uname()[2] # Kernel version (8.4.3)
559 major_version = int(kernel_version.split('.')[0])
561 if major_version < 8:
562 # On Mac OS X before 10.4, check if -arch and -isysroot
563 # are in CFLAGS or LDFLAGS and remove them if they are.
564 # This is needed when building extensions on a 10.3 system
565 # using a universal build of python.
566 for key in ('LDFLAGS', 'BASECFLAGS',
567 # a number of derived variables. These need to be
568 # patched up as well.
569 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
570 flags = _config_vars[key]
571 flags = re.sub('-arch\s+\w+\s', ' ', flags)
572 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
573 _config_vars[key] = flags
575 else:
577 # Allow the user to override the architecture flags using
578 # an environment variable.
579 # NOTE: This name was introduced by Apple in OSX 10.5 and
580 # is used by several scripting languages distributed with
581 # that OS release.
583 if 'ARCHFLAGS' in os.environ:
584 arch = os.environ['ARCHFLAGS']
585 for key in ('LDFLAGS', 'BASECFLAGS',
586 # a number of derived variables. These need to be
587 # patched up as well.
588 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
590 flags = _config_vars[key]
591 flags = re.sub('-arch\s+\w+\s', ' ', flags)
592 flags = flags + ' ' + arch
593 _config_vars[key] = flags
595 # If we're on OSX 10.5 or later and the user tries to
596 # compiles an extension using an SDK that is not present
597 # on the current machine it is better to not use an SDK
598 # than to fail.
600 # The major usecase for this is users using a Python.org
601 # binary installer on OSX 10.6: that installer uses
602 # the 10.4u SDK, but that SDK is not installed by default
603 # when you install Xcode.
605 m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS'])
606 if m is not None:
607 sdk = m.group(1)
608 if not os.path.exists(sdk):
609 for key in ('LDFLAGS', 'BASECFLAGS',
610 # a number of derived variables. These need to be
611 # patched up as well.
612 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
614 flags = _config_vars[key]
615 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
616 _config_vars[key] = flags
618 if args:
619 vals = []
620 for name in args:
621 vals.append(_config_vars.get(name))
622 return vals
623 else:
624 return _config_vars
626 def get_config_var(name):
627 """Return the value of a single variable using the dictionary
628 returned by 'get_config_vars()'. Equivalent to
629 get_config_vars().get(name)
631 return get_config_vars().get(name)