py-cvs-2001_07_13 (Rev 1.3) merge
[python/dscho.git] / Lib / distutils / sysconfig.py
blobd013d1b8328820c457970ea779d22eadc831b2af
1 """Provide access to Python's configuration information. The specific names
2 defined in the module depend heavily on the platform and configuration.
4 Written by: Fred L. Drake, Jr.
5 Email: <fdrake@acm.org>
6 Initial date: 17-Dec-1998
7 """
9 __revision__ = "$Id$"
11 import os
12 import re
13 import string
14 import sys
16 from errors import DistutilsPlatformError
18 # These are needed in a couple of spots, so just compute them once.
19 PREFIX = os.path.normpath(sys.prefix)
20 EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
22 # Boolean; if it's true, we're still building Python, so
23 # we use different (hard-wired) directories.
25 python_build = 0
27 def set_python_build():
28 """Set the python_build flag to true; this means that we're
29 building Python itself. Only called from the setup.py script
30 shipped with Python.
31 """
33 global python_build
34 python_build = 1
36 def get_python_inc(plat_specific=0, prefix=None):
37 """Return the directory containing installed Python header files.
39 If 'plat_specific' is false (the default), this is the path to the
40 non-platform-specific header files, i.e. Python.h and so on;
41 otherwise, this is the path to platform-specific header files
42 (namely config.h).
44 If 'prefix' is supplied, use it instead of sys.prefix or
45 sys.exec_prefix -- i.e., ignore 'plat_specific'.
46 """
47 if prefix is None:
48 prefix = (plat_specific and EXEC_PREFIX or PREFIX)
49 if os.name == "posix":
50 if python_build:
51 return "Include/"
52 return os.path.join(prefix, "include", "python" + sys.version[:3])
53 elif os.name == "nt":
54 return os.path.join(prefix, "Include") # include or Include?
55 elif os.name == "mac":
56 return os.path.join(prefix, "Include")
57 else:
58 raise DistutilsPlatformError, \
59 ("I don't know where Python installs its C header files " +
60 "on platform '%s'") % os.name
63 def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
64 """Return the directory containing the Python library (standard or
65 site additions).
67 If 'plat_specific' is true, return the directory containing
68 platform-specific modules, i.e. any module from a non-pure-Python
69 module distribution; otherwise, return the platform-shared library
70 directory. If 'standard_lib' is true, return the directory
71 containing standard Python library modules; otherwise, return the
72 directory for site-specific modules.
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)
80 if os.name == "posix":
81 libpython = os.path.join(prefix,
82 "lib", "python" + sys.version[:3])
83 if standard_lib:
84 return libpython
85 else:
86 return os.path.join(libpython, "site-packages")
88 elif os.name == "nt":
89 if standard_lib:
90 return os.path.join(PREFIX, "Lib")
91 else:
92 return prefix
94 elif os.name == "mac":
95 if plat_specific:
96 if standard_lib:
97 return os.path.join(EXEC_PREFIX, "Mac", "Plugins")
98 else:
99 raise DistutilsPlatformError, \
100 "OK, where DO site-specific extensions go on the Mac?"
101 else:
102 if standard_lib:
103 return os.path.join(PREFIX, "Lib")
104 else:
105 raise DistutilsPlatformError, \
106 "OK, where DO site-specific modules go on the Mac?"
107 else:
108 raise DistutilsPlatformError, \
109 ("I don't know where Python installs its library " +
110 "on platform '%s'") % os.name
112 # get_python_lib()
115 def customize_compiler (compiler):
116 """Do any platform-specific customization of the CCompiler instance
117 'compiler'. Mainly needed on Unix, so we can plug in the information
118 that varies across Unices and is stored in Python's Makefile.
120 if compiler.compiler_type == "unix":
121 (cc, opt, ccshared, ldshared, so_ext) = \
122 get_config_vars('CC', 'OPT', 'CCSHARED', 'LDSHARED', 'SO')
124 cc_cmd = cc + ' ' + opt
125 compiler.set_executables(
126 preprocessor=cc + " -E", # not always!
127 compiler=cc_cmd,
128 compiler_so=cc_cmd + ' ' + ccshared,
129 linker_so=ldshared,
130 linker_exe=cc)
132 compiler.shared_lib_extension = so_ext
135 def get_config_h_filename():
136 """Return full pathname of installed config.h file."""
137 if python_build: inc_dir = '.'
138 else: inc_dir = get_python_inc(plat_specific=1)
139 return os.path.join(inc_dir, "config.h")
142 def get_makefile_filename():
143 """Return full pathname of installed Makefile from the Python build."""
144 if python_build:
145 return './Makefile'
146 lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
147 return os.path.join(lib_dir, "config", "Makefile")
150 def parse_config_h(fp, g=None):
151 """Parse a config.h-style file.
153 A dictionary containing name/value pairs is returned. If an
154 optional dictionary is passed in as the second argument, it is
155 used instead of a new dictionary.
157 if g is None:
158 g = {}
159 define_rx = re.compile("#define ([A-Z][A-Z0-9_]+) (.*)\n")
160 undef_rx = re.compile("/[*] #undef ([A-Z][A-Z0-9_]+) [*]/\n")
162 while 1:
163 line = fp.readline()
164 if not line:
165 break
166 m = define_rx.match(line)
167 if m:
168 n, v = m.group(1, 2)
169 try: v = string.atoi(v)
170 except ValueError: pass
171 g[n] = v
172 else:
173 m = undef_rx.match(line)
174 if m:
175 g[m.group(1)] = 0
176 return g
179 # Regexes needed for parsing Makefile (and similar syntaxes,
180 # like old-style Setup files).
181 _variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
182 _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
183 _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
185 def parse_makefile(fn, g=None):
186 """Parse a Makefile-style file.
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.
193 from distutils.text_file import TextFile
194 fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
196 if g is None:
197 g = {}
198 done = {}
199 notdone = {}
201 while 1:
202 line = fp.readline()
203 if line is None: # eof
204 break
205 m = _variable_rx.match(line)
206 if m:
207 n, v = m.group(1, 2)
208 v = string.strip(v)
209 if "$" in v:
210 notdone[n] = v
211 else:
212 try: v = string.atoi(v)
213 except ValueError: pass
214 done[n] = v
216 # do variable interpolation here
217 while notdone:
218 for name in notdone.keys():
219 value = notdone[name]
220 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
221 if m:
222 n = m.group(1)
223 if done.has_key(n):
224 after = value[m.end():]
225 value = value[:m.start()] + str(done[n]) + after
226 if "$" in after:
227 notdone[name] = value
228 else:
229 try: value = string.atoi(value)
230 except ValueError:
231 done[name] = string.strip(value)
232 else:
233 done[name] = value
234 del notdone[name]
235 elif notdone.has_key(n):
236 # get it on a subsequent round
237 pass
238 else:
239 done[n] = ""
240 after = value[m.end():]
241 value = value[:m.start()] + after
242 if "$" in after:
243 notdone[name] = value
244 else:
245 try: value = string.atoi(value)
246 except ValueError:
247 done[name] = string.strip(value)
248 else:
249 done[name] = value
250 del notdone[name]
251 else:
252 # bogus variable reference; just drop it since we can't deal
253 del notdone[name]
255 fp.close()
257 # save the results in the global dictionary
258 g.update(done)
259 return g
262 def expand_makefile_vars(s, vars):
263 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
264 'string' according to 'vars' (a dictionary mapping variable names to
265 values). Variables not present in 'vars' are silently expanded to the
266 empty string. The variable values in 'vars' should not contain further
267 variable expansions; if 'vars' is the output of 'parse_makefile()',
268 you're fine. Returns a variable-expanded version of 's'.
271 # This algorithm does multiple expansion, so if vars['foo'] contains
272 # "${bar}", it will expand ${foo} to ${bar}, and then expand
273 # ${bar}... and so forth. This is fine as long as 'vars' comes from
274 # 'parse_makefile()', which takes care of such expansions eagerly,
275 # according to make's variable expansion semantics.
277 while 1:
278 m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
279 if m:
280 name = m.group(1)
281 (beg, end) = m.span()
282 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
283 else:
284 break
285 return s
288 _config_vars = None
290 def _init_posix():
291 """Initialize the module as appropriate for POSIX systems."""
292 g = {}
293 # load the installed Makefile:
294 try:
295 filename = get_makefile_filename()
296 parse_makefile(filename, g)
297 except IOError, msg:
298 my_msg = "invalid Python installation: unable to open %s" % filename
299 if hasattr(msg, "strerror"):
300 my_msg = my_msg + " (%s)" % msg.strerror
302 raise DistutilsPlatformError, my_msg
305 # On AIX, there are wrong paths to the linker scripts in the Makefile
306 # -- these paths are relative to the Python source, but when installed
307 # the scripts are in another directory.
308 if python_build:
309 g['LDSHARED'] = g['BLDSHARED']
311 global _config_vars
312 _config_vars = g
315 def _init_nt():
316 """Initialize the module as appropriate for NT"""
317 g = {}
318 # set basic install directories
319 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
320 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
322 # XXX hmmm.. a normal install puts include files here
323 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
325 g['SO'] = '.pyd'
326 g['EXE'] = ".exe"
328 global _config_vars
329 _config_vars = g
332 def _init_mac():
333 """Initialize the module as appropriate for Macintosh systems"""
334 g = {}
335 # set basic install directories
336 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
337 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
339 # XXX hmmm.. a normal install puts include files here
340 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
342 import MacOS
343 if not hasattr(MacOS, 'runtimemodel'):
344 g['SO'] = '.ppc.slb'
345 else:
346 g['SO'] = '.%s.slb' % MacOS.runtimemodel
348 # XXX are these used anywhere?
349 g['install_lib'] = os.path.join(EXEC_PREFIX, "Lib")
350 g['install_platlib'] = os.path.join(EXEC_PREFIX, "Mac", "Lib")
352 global _config_vars
353 _config_vars = g
356 def get_config_vars(*args):
357 """With no arguments, return a dictionary of all configuration
358 variables relevant for the current platform. Generally this includes
359 everything needed to build extensions and install both pure modules and
360 extensions. On Unix, this means every variable defined in Python's
361 installed Makefile; on Windows and Mac OS it's a much smaller set.
363 With arguments, return a list of values that result from looking up
364 each argument in the configuration variable dictionary.
366 global _config_vars
367 if _config_vars is None:
368 func = globals().get("_init_" + os.name)
369 if func:
370 func()
371 else:
372 _config_vars = {}
374 # Normalized versions of prefix and exec_prefix are handy to have;
375 # in fact, these are the standard versions used most places in the
376 # Distutils.
377 _config_vars['prefix'] = PREFIX
378 _config_vars['exec_prefix'] = EXEC_PREFIX
380 if args:
381 vals = []
382 for name in args:
383 vals.append(_config_vars.get(name))
384 return vals
385 else:
386 return _config_vars
388 def get_config_var(name):
389 """Return the value of a single variable using the dictionary
390 returned by 'get_config_vars()'. Equivalent to
391 get_config_vars().get(name)
393 return get_config_vars().get(name)