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
8
Written by: Fred L. Drake, Jr.
9
Email: <fdrake@acm.org>
12
__revision__ = "$Id: sysconfig.py 69487 2009-02-10 12:36:33Z tarek.ziade $"
19
from .errors import DistutilsPlatformError
21
# These are needed in a couple of spots, so just compute them once.
22
PREFIX = os.path.normpath(sys.prefix)
23
EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
25
# Path to the base directory of the project. On Windows the binary may
26
# live in project/PCBuild9. If we're dealing with an x64 Windows build,
27
# it'll live in project/PCbuild/amd64.
28
project_base = os.path.dirname(os.path.abspath(sys.executable))
29
if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
30
project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
32
if os.name == "nt" and "\\pc\\v" in project_base[-10:].lower():
33
project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
36
if os.name == "nt" and "\\pcbuild\\amd64" in project_base[-14:].lower():
37
project_base = os.path.abspath(os.path.join(project_base, os.path.pardir,
40
# python_build: (Boolean) if true, we're either building Python or
41
# building an extension with an un-installed Python, so we use
42
# different (hard-wired) directories.
43
# Setup.local is available for Makefile builds including VPATH builds,
44
# Setup.dist is available on Windows
46
for fn in ("Setup.dist", "Setup.local"):
47
if os.path.isfile(os.path.join(project_base, "Modules", fn)):
50
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'
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
68
If 'prefix' is supplied, use it instead of sys.prefix or
69
sys.exec_prefix -- i.e., ignore 'plat_specific'.
72
prefix = plat_specific and EXEC_PREFIX or PREFIX
73
if os.name == "posix":
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"
80
base = os.path.dirname(os.path.abspath(sys.executable))
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())
88
return os.path.join(prefix, "include")
89
elif os.name == "mac":
91
return os.path.join(prefix, "Mac", "Include")
93
return os.path.join(prefix, "Include")
94
elif os.name == "os2":
95
return os.path.join(prefix, "Include")
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
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'.
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())
125
return os.path.join(libpython, "site-packages")
126
elif os.name == "nt":
128
return os.path.join(prefix, "Lib")
130
if get_python_version() < "2.2":
133
return os.path.join(prefix, "Lib", "site-packages")
134
elif os.name == "mac":
137
return os.path.join(prefix, "Lib", "lib-dynload")
139
return os.path.join(prefix, "Lib", "site-packages")
142
return os.path.join(prefix, "Lib")
144
return os.path.join(prefix, "Lib", "site-packages")
145
elif os.name == "os2":
147
return os.path.join(prefix, "Lib")
149
return os.path.join(prefix, "Lib", "site-packages")
151
raise DistutilsPlatformError(
152
"I don't know where Python installs its library "
153
"on platform '%s'" % os.name)
156
def customize_compiler(compiler):
157
"""Do any platform-specific customization of a CCompiler instance.
159
Mainly needed on Unix, so we can plug in the information that
160
varies across Unices and is stored in Python's Makefile.
162
if compiler.compiler_type == "unix":
163
(cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar) = \
164
get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
165
'CCSHARED', 'LDSHARED', 'SO', 'AR')
167
if 'CC' in os.environ:
168
cc = os.environ['CC']
169
if 'CXX' in os.environ:
170
cxx = os.environ['CXX']
171
if 'LDSHARED' in os.environ:
172
ldshared = os.environ['LDSHARED']
173
if 'CPP' in os.environ:
174
cpp = os.environ['CPP']
176
cpp = cc + " -E" # not always
177
if 'LDFLAGS' in os.environ:
178
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
179
if 'CFLAGS' in os.environ:
180
cflags = opt + ' ' + os.environ['CFLAGS']
181
ldshared = ldshared + ' ' + os.environ['CFLAGS']
182
if 'CPPFLAGS' in os.environ:
183
cpp = cpp + ' ' + os.environ['CPPFLAGS']
184
cflags = cflags + ' ' + os.environ['CPPFLAGS']
185
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
186
if 'AR' in os.environ:
187
ar = os.environ['AR']
189
cc_cmd = cc + ' ' + cflags
190
compiler.set_executables(
193
compiler_so=cc_cmd + ' ' + ccshared,
199
compiler.shared_lib_extension = so_ext
202
def get_config_h_filename():
203
"""Return full pathname of installed pyconfig.h file."""
206
inc_dir = os.path.join(project_base, "PC")
208
inc_dir = project_base
210
inc_dir = get_python_inc(plat_specific=1)
211
if get_python_version() < '2.2':
212
config_h = 'config.h'
214
# The name of the config.h file changed in 2.2
215
config_h = 'pyconfig.h'
216
return os.path.join(inc_dir, config_h)
219
def get_makefile_filename():
220
"""Return full pathname of installed Makefile from the Python build."""
222
return os.path.join(os.path.dirname(sys.executable), "Makefile")
223
lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
224
return os.path.join(lib_dir, "config", "Makefile")
227
def parse_config_h(fp, g=None):
228
"""Parse a config.h-style file.
230
A dictionary containing name/value pairs is returned. If an
231
optional dictionary is passed in as the second argument, it is
232
used instead of a new dictionary.
236
define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
237
undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
243
m = define_rx.match(line)
247
except ValueError: pass
250
m = undef_rx.match(line)
256
# Regexes needed for parsing Makefile (and similar syntaxes,
257
# like old-style Setup files).
258
_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
259
_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
260
_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
262
def parse_makefile(fn, g=None):
263
"""Parse a Makefile-style file.
265
A dictionary containing name/value pairs is returned. If an
266
optional dictionary is passed in as the second argument, it is
267
used instead of a new dictionary.
269
from distutils.text_file import TextFile
270
fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
279
if line is None: # eof
281
m = _variable_rx.match(line)
289
except ValueError: pass
292
# do variable interpolation here
294
for name in list(notdone):
295
value = notdone[name]
296
m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
303
# get it on a subsequent round
305
elif n in os.environ:
306
# do it like make: fall back to environment
311
after = value[m.end():]
312
value = value[:m.start()] + item + after
314
notdone[name] = value
316
try: value = int(value)
318
done[name] = value.strip()
323
# bogus variable reference; just drop it since we can't deal
328
# save the results in the global dictionary
333
def expand_makefile_vars(s, vars):
334
"""Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
335
'string' according to 'vars' (a dictionary mapping variable names to
336
values). Variables not present in 'vars' are silently expanded to the
337
empty string. The variable values in 'vars' should not contain further
338
variable expansions; if 'vars' is the output of 'parse_makefile()',
339
you're fine. Returns a variable-expanded version of 's'.
342
# This algorithm does multiple expansion, so if vars['foo'] contains
343
# "${bar}", it will expand ${foo} to ${bar}, and then expand
344
# ${bar}... and so forth. This is fine as long as 'vars' comes from
345
# 'parse_makefile()', which takes care of such expansions eagerly,
346
# according to make's variable expansion semantics.
349
m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
351
(beg, end) = m.span()
352
s = s[0:beg] + vars.get(m.group(1)) + s[end:]
361
"""Initialize the module as appropriate for POSIX systems."""
363
# load the installed Makefile:
365
filename = get_makefile_filename()
366
parse_makefile(filename, g)
367
except IOError as msg:
368
my_msg = "invalid Python installation: unable to open %s" % filename
369
if hasattr(msg, "strerror"):
370
my_msg = my_msg + " (%s)" % msg.strerror
372
raise DistutilsPlatformError(my_msg)
374
# load the installed pyconfig.h:
376
filename = get_config_h_filename()
377
parse_config_h(io.open(filename), g)
378
except IOError as msg:
379
my_msg = "invalid Python installation: unable to open %s" % filename
380
if hasattr(msg, "strerror"):
381
my_msg = my_msg + " (%s)" % msg.strerror
383
raise DistutilsPlatformError(my_msg)
385
# On MacOSX we need to check the setting of the environment variable
386
# MACOSX_DEPLOYMENT_TARGET: configure bases some choices on it so
387
# it needs to be compatible.
388
# If it isn't set we set it to the configure-time value
389
if sys.platform == 'darwin' and 'MACOSX_DEPLOYMENT_TARGET' in g:
390
cfg_target = g['MACOSX_DEPLOYMENT_TARGET']
391
cur_target = os.getenv('MACOSX_DEPLOYMENT_TARGET', '')
393
cur_target = cfg_target
394
os.putenv('MACOSX_DEPLOYMENT_TARGET', cfg_target)
395
elif [int(x) for x in cfg_target.split('.')] > [int(x) for x in cur_target.split('.')]:
396
my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: now "%s" but "%s" during configure'
397
% (cur_target, cfg_target))
398
raise DistutilsPlatformError(my_msg)
400
# On AIX, there are wrong paths to the linker scripts in the Makefile
401
# -- these paths are relative to the Python source, but when installed
402
# the scripts are in another directory.
404
g['LDSHARED'] = g['BLDSHARED']
406
elif get_python_version() < '2.1':
407
# The following two branches are for 1.5.2 compatibility.
408
if sys.platform == 'aix4': # what about AIX 3.x ?
409
# Linker script is in the config directory, not in Modules as the
411
python_lib = get_python_lib(standard_lib=1)
412
ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
413
python_exp = os.path.join(python_lib, 'config', 'python.exp')
415
g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
422
"""Initialize the module as appropriate for NT"""
424
# set basic install directories
425
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
426
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
428
# XXX hmmm.. a normal install puts include files here
429
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
433
g['VERSION'] = get_python_version().replace(".", "")
434
g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
441
"""Initialize the module as appropriate for Macintosh systems"""
443
# set basic install directories
444
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
445
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
447
# XXX hmmm.. a normal install puts include files here
448
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
451
if not hasattr(MacOS, 'runtimemodel'):
454
g['SO'] = '.%s.slb' % MacOS.runtimemodel
456
# XXX are these used anywhere?
457
g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
458
g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
460
# These are used by the extension module build
467
"""Initialize the module as appropriate for OS/2"""
469
# set basic install directories
470
g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
471
g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
473
# XXX hmmm.. a normal install puts include files here
474
g['INCLUDEPY'] = get_python_inc(plat_specific=0)
483
def get_config_vars(*args):
484
"""With no arguments, return a dictionary of all configuration
485
variables relevant for the current platform. Generally this includes
486
everything needed to build extensions and install both pure modules and
487
extensions. On Unix, this means every variable defined in Python's
488
installed Makefile; on Windows and Mac OS it's a much smaller set.
490
With arguments, return a list of values that result from looking up
491
each argument in the configuration variable dictionary.
494
if _config_vars is None:
495
func = globals().get("_init_" + os.name)
501
# Normalized versions of prefix and exec_prefix are handy to have;
502
# in fact, these are the standard versions used most places in the
504
_config_vars['prefix'] = PREFIX
505
_config_vars['exec_prefix'] = EXEC_PREFIX
507
# Convert srcdir into an absolute path if it appears necessary.
508
# Normally it is relative to the build directory. However, during
509
# testing, for example, we might be running a non-installed python
510
# from a different directory.
511
if python_build and os.name == "posix":
512
base = os.path.dirname(os.path.abspath(sys.executable))
513
if (not os.path.isabs(_config_vars['srcdir']) and
514
base != os.getcwd()):
515
# srcdir is relative and we are not in the same directory
516
# as the executable. Assume executable is in the build
517
# directory and make srcdir absolute.
518
srcdir = os.path.join(base, _config_vars['srcdir'])
519
_config_vars['srcdir'] = os.path.normpath(srcdir)
521
if sys.platform == 'darwin':
522
kernel_version = os.uname()[2] # Kernel version (8.4.3)
523
major_version = int(kernel_version.split('.')[0])
525
if major_version < 8:
526
# On Mac OS X before 10.4, check if -arch and -isysroot
527
# are in CFLAGS or LDFLAGS and remove them if they are.
528
# This is needed when building extensions on a 10.3 system
529
# using a universal build of python.
530
for key in ('LDFLAGS', 'BASECFLAGS',
531
# a number of derived variables. These need to be
532
# patched up as well.
533
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
534
flags = _config_vars[key]
535
flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
536
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
537
_config_vars[key] = flags
541
# Allow the user to override the architecture flags using
542
# an environment variable.
543
# NOTE: This name was introduced by Apple in OSX 10.5 and
544
# is used by several scripting languages distributed with
547
if 'ARCHFLAGS' in os.environ:
548
arch = os.environ['ARCHFLAGS']
549
for key in ('LDFLAGS', 'BASECFLAGS',
550
# a number of derived variables. These need to be
551
# patched up as well.
552
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
554
flags = _config_vars[key]
555
flags = re.sub('-arch\s+\w+\s', ' ', flags)
556
flags = flags + ' ' + arch
557
_config_vars[key] = flags
562
vals.append(_config_vars.get(name))
567
def get_config_var(name):
568
"""Return the value of a single variable using the dictionary
569
returned by 'get_config_vars()'. Equivalent to
570
get_config_vars().get(name)
572
return get_config_vars().get(name)