304 lines
9.9 KiB
Python
304 lines
9.9 KiB
Python
"""Provide access to Python's configuration information. The specific names
|
|
defined in the module depend heavily on the platform and configuration.
|
|
|
|
Written by: Fred L. Drake, Jr.
|
|
Email: <fdrake@acm.org>
|
|
Initial date: 17-Dec-1998
|
|
"""
|
|
|
|
__revision__ = "$Id$"
|
|
|
|
import os
|
|
import re
|
|
import string
|
|
import sys
|
|
|
|
from errors import DistutilsPlatformError
|
|
|
|
|
|
PREFIX = os.path.normpath(sys.prefix)
|
|
EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
|
|
|
|
|
|
def get_python_inc(plat_specific=0, prefix=None):
|
|
"""Return the directory containing installed Python header files.
|
|
|
|
If 'plat_specific' is false (the default), this is the path to the
|
|
non-platform-specific header files, i.e. Python.h and so on;
|
|
otherwise, this is the path to platform-specific header files
|
|
(namely config.h).
|
|
|
|
If 'prefix' is supplied, use it instead of sys.prefix or
|
|
sys.exec_prefix -- i.e., ignore 'plat_specific'.
|
|
"""
|
|
if prefix is None:
|
|
prefix = (plat_specific and EXEC_PREFIX or PREFIX)
|
|
if os.name == "posix":
|
|
return os.path.join(prefix, "include", "python" + sys.version[:3])
|
|
elif os.name == "nt":
|
|
return os.path.join(prefix, "Include") # include or Include?
|
|
elif os.name == "mac":
|
|
return os.path.join(prefix, "Include")
|
|
else:
|
|
raise DistutilsPlatformError, \
|
|
("I don't know where Python installs its C header files " +
|
|
"on platform '%s'") % os.name
|
|
|
|
|
|
def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
|
|
"""Return the directory containing the Python library (standard or
|
|
site additions).
|
|
|
|
If 'plat_specific' is true, return the directory containing
|
|
platform-specific modules, i.e. any module from a non-pure-Python
|
|
module distribution; otherwise, return the platform-shared library
|
|
directory. If 'standard_lib' is true, return the directory
|
|
containing standard Python library modules; otherwise, return the
|
|
directory for site-specific modules.
|
|
|
|
If 'prefix' is supplied, use it instead of sys.prefix or
|
|
sys.exec_prefix -- i.e., ignore 'plat_specific'.
|
|
"""
|
|
if prefix is None:
|
|
prefix = (plat_specific and EXEC_PREFIX or PREFIX)
|
|
|
|
if os.name == "posix":
|
|
libpython = os.path.join(prefix,
|
|
"lib", "python" + sys.version[:3])
|
|
if standard_lib:
|
|
return libpython
|
|
else:
|
|
return os.path.join(libpython, "site-packages")
|
|
|
|
elif os.name == "nt":
|
|
if standard_lib:
|
|
return os.path.join(PREFIX, "Lib")
|
|
else:
|
|
return prefix
|
|
|
|
elif os.name == "mac":
|
|
if platform_specific:
|
|
if standard_lib:
|
|
return os.path.join(EXEC_PREFIX, "Mac", "Plugins")
|
|
else:
|
|
raise DistutilsPlatformError, \
|
|
"OK, where DO site-specific extensions go on the Mac?"
|
|
else:
|
|
if standard_lib:
|
|
return os.path.join(PREFIX, "Lib")
|
|
else:
|
|
raise DistutilsPlatformError, \
|
|
"OK, where DO site-specific modules go on the Mac?"
|
|
else:
|
|
raise DistutilsPlatformError, \
|
|
("I don't know where Python installs its library " +
|
|
"on platform '%s'") % os.name
|
|
|
|
# get_python_lib()
|
|
|
|
|
|
def get_config_h_filename():
|
|
"""Return full pathname of installed config.h file."""
|
|
inc_dir = get_python_inc(plat_specific=1)
|
|
return os.path.join(inc_dir, "config.h")
|
|
|
|
|
|
def get_makefile_filename():
|
|
"""Return full pathname of installed Makefile from the Python build."""
|
|
lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
|
|
return os.path.join(lib_dir, "config", "Makefile")
|
|
|
|
|
|
def parse_config_h(fp, g=None):
|
|
"""Parse a config.h-style file.
|
|
|
|
A dictionary containing name/value pairs is returned. If an
|
|
optional dictionary is passed in as the second argument, it is
|
|
used instead of a new dictionary.
|
|
"""
|
|
if g is None:
|
|
g = {}
|
|
define_rx = re.compile("#define ([A-Z][A-Z0-9_]+) (.*)\n")
|
|
undef_rx = re.compile("/[*] #undef ([A-Z][A-Z0-9_]+) [*]/\n")
|
|
#
|
|
while 1:
|
|
line = fp.readline()
|
|
if not line:
|
|
break
|
|
m = define_rx.match(line)
|
|
if m:
|
|
n, v = m.group(1, 2)
|
|
try: v = string.atoi(v)
|
|
except ValueError: pass
|
|
g[n] = v
|
|
else:
|
|
m = undef_rx.match(line)
|
|
if m:
|
|
g[m.group(1)] = 0
|
|
return g
|
|
|
|
def parse_makefile(fp, g=None):
|
|
"""Parse a Makefile-style file.
|
|
|
|
A dictionary containing name/value pairs is returned. If an
|
|
optional dictionary is passed in as the second argument, it is
|
|
used instead of a new dictionary.
|
|
|
|
"""
|
|
if g is None:
|
|
g = {}
|
|
variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)\n")
|
|
done = {}
|
|
notdone = {}
|
|
#
|
|
while 1:
|
|
line = fp.readline()
|
|
if not line:
|
|
break
|
|
m = variable_rx.match(line)
|
|
if m:
|
|
n, v = m.group(1, 2)
|
|
v = string.strip(v)
|
|
if "$" in v:
|
|
notdone[n] = v
|
|
else:
|
|
try: v = string.atoi(v)
|
|
except ValueError: pass
|
|
done[n] = v
|
|
|
|
# do variable interpolation here
|
|
findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
|
|
findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
|
|
while notdone:
|
|
for name in notdone.keys():
|
|
value = notdone[name]
|
|
m = findvar1_rx.search(value)
|
|
if not m:
|
|
m = findvar2_rx.search(value)
|
|
if m:
|
|
n = m.group(1)
|
|
if done.has_key(n):
|
|
after = value[m.end():]
|
|
value = value[:m.start()] + done[n] + after
|
|
if "$" in after:
|
|
notdone[name] = value
|
|
else:
|
|
try: value = string.atoi(value)
|
|
except ValueError: pass
|
|
done[name] = string.strip(value)
|
|
del notdone[name]
|
|
elif notdone.has_key(n):
|
|
# get it on a subsequent round
|
|
pass
|
|
else:
|
|
done[n] = ""
|
|
after = value[m.end():]
|
|
value = value[:m.start()] + after
|
|
if "$" in after:
|
|
notdone[name] = value
|
|
else:
|
|
try: value = string.atoi(value)
|
|
except ValueError: pass
|
|
done[name] = string.strip(value)
|
|
del notdone[name]
|
|
else:
|
|
# bogus variable reference; just drop it since we can't deal
|
|
del notdone[name]
|
|
|
|
# "Fix" all pathnames in the Makefile that are explicitly relative,
|
|
# ie. that start with "./". This is a kludge to fix the "./ld_so_aix"
|
|
# problem, the nature of which is that Python's installed Makefile
|
|
# refers to "./ld_so_aix", but when we are building extensions we are
|
|
# far from the directory where Python's Makefile (and ld_so_aix, for
|
|
# that matter) is installed. Unfortunately, there are several other
|
|
# relative pathnames in the Makefile, and this fix doesn't fix them,
|
|
# because the layout of Python's source tree -- which is what the
|
|
# Makefile refers to -- is not fully preserved in the Python
|
|
# installation. Grumble.
|
|
from os.path import normpath, join, dirname
|
|
for (name, value) in done.items():
|
|
if value[0:2] == "./":
|
|
done[name] = normpath(join(dirname(fp.name), value))
|
|
|
|
# save the results in the global dictionary
|
|
g.update(done)
|
|
return g
|
|
|
|
|
|
def _init_posix():
|
|
"""Initialize the module as appropriate for POSIX systems."""
|
|
g = globals()
|
|
# load the installed Makefile:
|
|
try:
|
|
filename = get_makefile_filename()
|
|
file = open(filename)
|
|
except IOError, msg:
|
|
my_msg = "invalid Python installation: unable to open %s" % filename
|
|
if hasattr(msg, "strerror"):
|
|
my_msg = my_msg + " (%s)" % msg.strerror
|
|
|
|
raise DistutilsPlatformError, my_msg
|
|
|
|
parse_makefile(file, g)
|
|
|
|
|
|
def _init_nt():
|
|
"""Initialize the module as appropriate for NT"""
|
|
g = globals()
|
|
# set basic install directories
|
|
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
|
|
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
|
|
|
|
# XXX hmmm.. a normal install puts include files here
|
|
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
|
|
|
|
g['SO'] = '.pyd'
|
|
g['exec_prefix'] = EXEC_PREFIX
|
|
|
|
# These are needed for the CygwinCCompiler and Mingw32CCompiler
|
|
# classes, which are just UnixCCompiler classes that happen to work on
|
|
# Windows. UnixCCompiler expects to find these values in sysconfig, so
|
|
# here they are. The fact that other Windows compilers don't need
|
|
# these values is pure luck (hmmm).
|
|
g['CC'] = "cc" # not gcc?
|
|
g['RANLIB'] = "ranlib"
|
|
g['AR'] = "ar"
|
|
g['OPT'] = "-O2"
|
|
g['SO'] = ".pyd"
|
|
g['LDSHARED'] = "ld"
|
|
g['CCSHARED'] = ""
|
|
g['EXE'] = ".exe"
|
|
|
|
|
|
def _init_mac():
|
|
"""Initialize the module as appropriate for Macintosh systems"""
|
|
g = globals()
|
|
# set basic install directories
|
|
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
|
|
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
|
|
|
|
# XXX hmmm.. a normal install puts include files here
|
|
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
|
|
|
|
g['SO'] = '.ppc.slb'
|
|
g['exec_prefix'] = EXEC_PREFIX
|
|
print sys.prefix, PREFIX
|
|
|
|
# XXX are these used anywhere?
|
|
g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
|
|
g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
|
|
|
|
|
|
try:
|
|
exec "_init_" + os.name
|
|
except NameError:
|
|
# not needed for this platform
|
|
pass
|
|
else:
|
|
exec "_init_%s()" % os.name
|
|
|
|
|
|
del _init_posix
|
|
del _init_nt
|
|
del _init_mac
|