source: python/trunk/Lib/distutils/sysconfig.py@ 391

Last change on this file since 391 was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 18.1 KB
Line 
1"""Provide access to Python's configuration information. The specific
2configuration variables available depend heavily on the platform and
3configuration. The values may be retrieved using
4get_config_var(name), and the list of variables is available via
5get_config_vars().keys(). Additional convenience functions are also
6available.
7
8Written by: Fred L. Drake, Jr.
9Email: <fdrake@acm.org>
10"""
11
12__revision__ = "$Id$"
13
14import os
15import re
16import string
17import sys
18
19from distutils.errors import DistutilsPlatformError
20
21# These are needed in a couple of spots, so just compute them once.
22PREFIX = os.path.normpath(sys.prefix)
23EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
24
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.
28project_base = os.path.dirname(os.path.abspath(sys.executable))
29if os.name == "nt" and "pcbuild" in project_base[-8:].lower():
30 project_base = os.path.abspath(os.path.join(project_base, os.path.pardir))
31# PC/VS7.1
32if 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,
34 os.path.pardir))
35# PC/AMD64
36if 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,
38 os.path.pardir))
39
40# set for cross builds
41if "_PYTHON_PROJECT_BASE" in os.environ:
42 # this is the build directory, at least for posix
43 project_base = os.path.normpath(os.environ["_PYTHON_PROJECT_BASE"])
44
45# python_build: (Boolean) if true, we're either building Python or
46# building an extension with an un-installed Python, so we use
47# different (hard-wired) directories.
48# Setup.local is available for Makefile builds including VPATH builds,
49# Setup.dist is available on Windows
50def _python_build():
51 for fn in ("Setup.dist", "Setup.local"):
52 if os.path.isfile(os.path.join(project_base, "Modules", fn)):
53 return True
54 return False
55python_build = _python_build()
56
57
58def get_python_version():
59 """Return a string containing the major and minor Python version,
60 leaving off the patchlevel. Sample return values could be '1.5'
61 or '2.2'.
62 """
63 return sys.version[:3]
64
65
66def get_python_inc(plat_specific=0, prefix=None):
67 """Return the directory containing installed Python header files.
68
69 If 'plat_specific' is false (the default), this is the path to the
70 non-platform-specific header files, i.e. Python.h and so on;
71 otherwise, this is the path to platform-specific header files
72 (namely pyconfig.h).
73
74 If 'prefix' is supplied, use it instead of sys.prefix or
75 sys.exec_prefix -- i.e., ignore 'plat_specific'.
76 """
77 if prefix is None:
78 prefix = plat_specific and EXEC_PREFIX or PREFIX
79
80 if os.name == "posix":
81 if python_build:
82 buildir = os.path.dirname(sys.executable)
83 if plat_specific:
84 # python.h is located in the buildir
85 inc_dir = buildir
86 else:
87 # the source dir is relative to the buildir
88 srcdir = os.path.abspath(os.path.join(buildir,
89 get_config_var('srcdir')))
90 # Include is located in the srcdir
91 inc_dir = os.path.join(srcdir, "Include")
92 return inc_dir
93 return os.path.join(prefix, "include", "python" + get_python_version())
94 elif os.name == "nt":
95 return os.path.join(prefix, "include")
96 elif os.name == "os2":
97 if python_build:
98 base = os.path.dirname(os.path.abspath(sys.executable))
99 if plat_specific:
100 inc_dir = base
101 else:
102 inc_dir = os.path.join(base, "Include")
103 if not os.path.exists(inc_dir):
104 inc_dir = os.path.join(os.path.dirname(base), "Include")
105 return inc_dir
106 return os.path.join(prefix, "include", "python" + get_python_version())
107 else:
108 raise DistutilsPlatformError(
109 "I don't know where Python installs its C header files "
110 "on platform '%s'" % os.name)
111
112
113def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
114 """Return the directory containing the Python library (standard or
115 site additions).
116
117 If 'plat_specific' is true, return the directory containing
118 platform-specific modules, i.e. any module from a non-pure-Python
119 module distribution; otherwise, return the platform-shared library
120 directory. If 'standard_lib' is true, return the directory
121 containing standard Python library modules; otherwise, return the
122 directory for site-specific modules.
123
124 If 'prefix' is supplied, use it instead of sys.prefix or
125 sys.exec_prefix -- i.e., ignore 'plat_specific'.
126 """
127 if prefix is None:
128 prefix = plat_specific and EXEC_PREFIX or PREFIX
129
130 if os.name == "posix":
131 libpython = os.path.join(prefix,
132 "lib", "python" + get_python_version())
133 if standard_lib:
134 return libpython
135 else:
136 return os.path.join(libpython, "site-packages")
137
138 elif os.name == "nt":
139 if standard_lib:
140 return os.path.join(prefix, "Lib")
141 else:
142 if get_python_version() < "2.2":
143 return prefix
144 else:
145 return os.path.join(prefix, "Lib", "site-packages")
146
147 elif os.name == "os2":
148 libpython = os.path.join(prefix,
149 "lib", "python" + get_python_version())
150 if standard_lib:
151 return libpython
152 else:
153 return os.path.join(libpython, "site-packages")
154
155 else:
156 raise DistutilsPlatformError(
157 "I don't know where Python installs its library "
158 "on platform '%s'" % os.name)
159
160
161
162def customize_compiler(compiler):
163 """Do any platform-specific customization of a CCompiler instance.
164
165 Mainly needed on Unix, so we can plug in the information that
166 varies across Unices and is stored in Python's Makefile.
167 """
168 if compiler.compiler_type == "unix" or compiler.compiler_type == "emx":
169 if sys.platform == "darwin":
170 # Perform first-time customization of compiler-related
171 # config vars on OS X now that we know we need a compiler.
172 # This is primarily to support Pythons from binary
173 # installers. The kind and paths to build tools on
174 # the user system may vary significantly from the system
175 # that Python itself was built on. Also the user OS
176 # version and build tools may not support the same set
177 # of CPU architectures for universal builds.
178 global _config_vars
179 if not _config_vars.get('CUSTOMIZED_OSX_COMPILER', ''):
180 import _osx_support
181 _osx_support.customize_compiler(_config_vars)
182 _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
183
184 (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
185 get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
186 'CCSHARED', 'LDSHARED', 'SO', 'AR',
187 'ARFLAGS')
188
189 if 'CC' in os.environ:
190 newcc = os.environ['CC']
191 if (sys.platform == 'darwin'
192 and 'LDSHARED' not in os.environ
193 and ldshared.startswith(cc)):
194 # On OS X, if CC is overridden, use that as the default
195 # command for LDSHARED as well
196 ldshared = newcc + ldshared[len(cc):]
197 cc = newcc
198 if 'CXX' in os.environ:
199 cxx = os.environ['CXX']
200 if 'LDSHARED' in os.environ:
201 ldshared = os.environ['LDSHARED']
202 if 'CPP' in os.environ:
203 cpp = os.environ['CPP']
204 else:
205 cpp = cc + " -E" # not always
206 if 'LDFLAGS' in os.environ:
207 ldshared = ldshared + ' ' + os.environ['LDFLAGS']
208 if 'CFLAGS' in os.environ:
209 cflags = opt + ' ' + os.environ['CFLAGS']
210 ldshared = ldshared + ' ' + os.environ['CFLAGS']
211 if 'CPPFLAGS' in os.environ:
212 cpp = cpp + ' ' + os.environ['CPPFLAGS']
213 cflags = cflags + ' ' + os.environ['CPPFLAGS']
214 ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
215 if 'AR' in os.environ:
216 ar = os.environ['AR']
217 if 'ARFLAGS' in os.environ:
218 archiver = ar + ' ' + os.environ['ARFLAGS']
219 else:
220 archiver = ar + ' ' + ar_flags
221
222 cc_cmd = cc + ' ' + cflags
223 compiler.set_executables(
224 preprocessor=cpp,
225 compiler=cc_cmd,
226 compiler_so=cc_cmd + ' ' + ccshared,
227 compiler_cxx=cxx,
228 linker_so=ldshared,
229 linker_exe=cc,
230 archiver=archiver)
231
232 compiler.shared_lib_extension = so_ext
233
234
235def get_config_h_filename():
236 """Return full pathname of installed pyconfig.h file."""
237 if python_build:
238 if os.name == "nt":
239 inc_dir = os.path.join(project_base, "PC")
240 else:
241 inc_dir = project_base
242 else:
243 inc_dir = get_python_inc(plat_specific=1)
244 if get_python_version() < '2.2':
245 config_h = 'config.h'
246 else:
247 # The name of the config.h file changed in 2.2
248 config_h = 'pyconfig.h'
249 return os.path.join(inc_dir, config_h)
250
251
252def get_makefile_filename():
253 """Return full pathname of installed Makefile from the Python build."""
254 if python_build:
255 return os.path.join(project_base, "Makefile")
256 lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
257 return os.path.join(lib_dir, "config", "Makefile")
258
259
260def parse_config_h(fp, g=None):
261 """Parse a config.h-style file.
262
263 A dictionary containing name/value pairs is returned. If an
264 optional dictionary is passed in as the second argument, it is
265 used instead of a new dictionary.
266 """
267 if g is None:
268 g = {}
269 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
270 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
271 #
272 while 1:
273 line = fp.readline()
274 if not line:
275 break
276 m = define_rx.match(line)
277 if m:
278 n, v = m.group(1, 2)
279 try: v = int(v)
280 except ValueError: pass
281 g[n] = v
282 else:
283 m = undef_rx.match(line)
284 if m:
285 g[m.group(1)] = 0
286 return g
287
288
289# Regexes needed for parsing Makefile (and similar syntaxes,
290# like old-style Setup files).
291_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
292_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
293_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
294
295def parse_makefile(fn, g=None):
296 """Parse a Makefile-style file.
297
298 A dictionary containing name/value pairs is returned. If an
299 optional dictionary is passed in as the second argument, it is
300 used instead of a new dictionary.
301 """
302 from distutils.text_file import TextFile
303 fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
304
305 if g is None:
306 g = {}
307 done = {}
308 notdone = {}
309
310 while 1:
311 line = fp.readline()
312 if line is None: # eof
313 break
314 m = _variable_rx.match(line)
315 if m:
316 n, v = m.group(1, 2)
317 v = v.strip()
318 # `$$' is a literal `$' in make
319 tmpv = v.replace('$$', '')
320
321 if "$" in tmpv:
322 notdone[n] = v
323 else:
324 try:
325 v = int(v)
326 except ValueError:
327 # insert literal `$'
328 done[n] = v.replace('$$', '$')
329 else:
330 done[n] = v
331
332 # do variable interpolation here
333 while notdone:
334 for name in notdone.keys():
335 value = notdone[name]
336 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
337 if m:
338 n = m.group(1)
339 found = True
340 if n in done:
341 item = str(done[n])
342 elif n in notdone:
343 # get it on a subsequent round
344 found = False
345 elif n in os.environ:
346 # do it like make: fall back to environment
347 item = os.environ[n]
348 else:
349 done[n] = item = ""
350 if found:
351 after = value[m.end():]
352 value = value[:m.start()] + item + after
353 if "$" in after:
354 notdone[name] = value
355 else:
356 try: value = int(value)
357 except ValueError:
358 done[name] = value.strip()
359 else:
360 done[name] = value
361 del notdone[name]
362 else:
363 # bogus variable reference; just drop it since we can't deal
364 del notdone[name]
365
366 fp.close()
367
368 # strip spurious spaces
369 for k, v in done.items():
370 if isinstance(v, str):
371 done[k] = v.strip()
372
373 # save the results in the global dictionary
374 g.update(done)
375 return g
376
377
378def expand_makefile_vars(s, vars):
379 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
380 'string' according to 'vars' (a dictionary mapping variable names to
381 values). Variables not present in 'vars' are silently expanded to the
382 empty string. The variable values in 'vars' should not contain further
383 variable expansions; if 'vars' is the output of 'parse_makefile()',
384 you're fine. Returns a variable-expanded version of 's'.
385 """
386
387 # This algorithm does multiple expansion, so if vars['foo'] contains
388 # "${bar}", it will expand ${foo} to ${bar}, and then expand
389 # ${bar}... and so forth. This is fine as long as 'vars' comes from
390 # 'parse_makefile()', which takes care of such expansions eagerly,
391 # according to make's variable expansion semantics.
392
393 while 1:
394 m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
395 if m:
396 (beg, end) = m.span()
397 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
398 else:
399 break
400 return s
401
402
403_config_vars = None
404
405def _init_posix():
406 """Initialize the module as appropriate for POSIX systems."""
407 # _sysconfigdata is generated at build time, see the sysconfig module
408 from _sysconfigdata import build_time_vars
409 global _config_vars
410 _config_vars = {}
411 _config_vars.update(build_time_vars)
412
413
414def _init_nt():
415 """Initialize the module as appropriate for NT"""
416 g = {}
417 # set basic install directories
418 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
419 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
420
421 # XXX hmmm.. a normal install puts include files here
422 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
423
424 g['SO'] = '.pyd'
425 g['EXE'] = ".exe"
426 g['VERSION'] = get_python_version().replace(".", "")
427 g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
428
429 global _config_vars
430 _config_vars = g
431
432
433def _init_os2():
434 """Initialize the module as appropriate for OS/2"""
435 g = {}
436 # load the installed Makefile:
437 try:
438 filename = get_makefile_filename()
439 parse_makefile(filename, g)
440 except IOError, msg:
441 my_msg = "invalid Python installation: unable to open %s" % filename
442 if hasattr(msg, "strerror"):
443 my_msg = my_msg + " (%s)" % msg.strerror
444
445 raise DistutilsPlatformError(my_msg)
446
447 # load the installed pyconfig.h:
448 try:
449 filename = get_config_h_filename()
450 parse_config_h(file(filename), g)
451 except IOError, msg:
452 my_msg = "invalid Python installation: unable to open %s" % filename
453 if hasattr(msg, "strerror"):
454 my_msg = my_msg + " (%s)" % msg.strerror
455
456 raise DistutilsPlatformError(my_msg)
457
458 # On AIX, there are wrong paths to the linker scripts in the Makefile
459 # -- these paths are relative to the Python source, but when installed
460 # the scripts are in another directory.
461 if python_build:
462 g['LDSHARED'] = g['BLDSHARED']
463
464 # OS/2 module
465
466 # set basic install directories
467 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
468 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
469
470 # XXX hmmm.. a normal install puts include files here
471 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
472
473 g['SO'] = '.pyd'
474 g['EXE'] = ".exe"
475
476 global _config_vars
477 _config_vars = g
478
479
480def get_config_vars(*args):
481 """With no arguments, return a dictionary of all configuration
482 variables relevant for the current platform. Generally this includes
483 everything needed to build extensions and install both pure modules and
484 extensions. On Unix, this means every variable defined in Python's
485 installed Makefile; on Windows and Mac OS it's a much smaller set.
486
487 With arguments, return a list of values that result from looking up
488 each argument in the configuration variable dictionary.
489 """
490 global _config_vars
491 if _config_vars is None:
492 func = globals().get("_init_" + os.name)
493 if func:
494 func()
495 else:
496 _config_vars = {}
497
498 # Normalized versions of prefix and exec_prefix are handy to have;
499 # in fact, these are the standard versions used most places in the
500 # Distutils.
501 _config_vars['prefix'] = PREFIX
502 _config_vars['exec_prefix'] = EXEC_PREFIX
503
504 # OS X platforms require special customization to handle
505 # multi-architecture, multi-os-version installers
506 if sys.platform == 'darwin':
507 import _osx_support
508 _osx_support.customize_config_vars(_config_vars)
509
510 if args:
511 vals = []
512 for name in args:
513 vals.append(_config_vars.get(name))
514 return vals
515 else:
516 return _config_vars
517
518def get_config_var(name):
519 """Return the value of a single variable using the dictionary
520 returned by 'get_config_vars()'. Equivalent to
521 get_config_vars().get(name)
522 """
523 return get_config_vars().get(name)
Note: See TracBrowser for help on using the repository browser.