blob: 4b193b2703c451c29fe2490c1cfb842cfa32830d [file] [log] [blame]
Fred Drake70b014d2001-07-18 18:39:56 +00001"""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.
Greg Ward1190ee31998-12-18 23:46:33 +00007
8Written by: Fred L. Drake, Jr.
9Email: <fdrake@acm.org>
Greg Ward1190ee31998-12-18 23:46:33 +000010"""
11
Greg Ward82d71ca2000-06-03 00:44:30 +000012__revision__ = "$Id$"
Greg Ward1190ee31998-12-18 23:46:33 +000013
Tarek Ziadédd7bef92010-03-05 00:16:02 +000014import os
Greg Ward9ddaaa11999-01-06 14:46:06 +000015import re
Tarek Ziadédd7bef92010-03-05 00:16:02 +000016import string
17import sys
Greg Ward1190ee31998-12-18 23:46:33 +000018
Tarek Ziadédd7bef92010-03-05 00:16:02 +000019from distutils.errors import DistutilsPlatformError
Greg Warda0ca3f22000-02-02 00:05:14 +000020
Tarek Ziadédd7bef92010-03-05 00:16:02 +000021# 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)
Tarek Ziadé0276c7a2010-01-26 21:21:54 +000024
Tarek Ziadédd7bef92010-03-05 00:16:02 +000025# 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))
Fred Drakec1ee39a2000-03-09 15:54:52 +000039
Tarek Ziadédd7bef92010-03-05 00:16:02 +000040# 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
Marc-André Lemburg2db7cd32008-02-05 14:50:40 +000045def _python_build():
Tarek Ziadédd7bef92010-03-05 00:16:02 +000046 for fn in ("Setup.dist", "Setup.local"):
47 if os.path.isfile(os.path.join(project_base, "Modules", fn)):
48 return True
49 return False
Marc-André Lemburg2db7cd32008-02-05 14:50:40 +000050python_build = _python_build()
Fred Drakec1ee39a2000-03-09 15:54:52 +000051
Tarek Ziadé5633a802010-01-23 09:23:15 +000052
Tarek Ziadédd7bef92010-03-05 00:16:02 +000053def get_python_version():
54 """Return a string containing the major and minor Python version,
55 leaving off the patchlevel. Sample return values could be '1.5'
56 or '2.2'.
57 """
58 return sys.version[:3]
59
60
61def get_python_inc(plat_specific=0, prefix=None):
62 """Return the directory containing installed Python header files.
Fred Drakec1ee39a2000-03-09 15:54:52 +000063
64 If 'plat_specific' is false (the default), this is the path to the
65 non-platform-specific header files, i.e. Python.h and so on;
66 otherwise, this is the path to platform-specific header files
Martin v. Löwis4f1cd8b2001-07-26 13:41:06 +000067 (namely pyconfig.h).
Fred Drakec1ee39a2000-03-09 15:54:52 +000068
Greg Wardd38e6f72000-04-10 01:17:49 +000069 If 'prefix' is supplied, use it instead of sys.prefix or
70 sys.exec_prefix -- i.e., ignore 'plat_specific'.
Fred Drakeb94b8492001-12-06 20:51:35 +000071 """
Tarek Ziadédd7bef92010-03-05 00:16:02 +000072 if prefix is None:
73 prefix = plat_specific and EXEC_PREFIX or PREFIX
Tarek Ziadéa5cd1822010-04-30 12:15:12 +000074
Tarek Ziadédd7bef92010-03-05 00:16:02 +000075 if os.name == "posix":
76 if python_build:
Tarek Ziadéa5cd1822010-04-30 12:15:12 +000077 buildir = os.path.dirname(sys.executable)
Tarek Ziadédd7bef92010-03-05 00:16:02 +000078 if plat_specific:
Tarek Ziadéa5cd1822010-04-30 12:15:12 +000079 # python.h is located in the buildir
80 inc_dir = buildir
Tarek Ziadédd7bef92010-03-05 00:16:02 +000081 else:
Tarek Ziadéa5cd1822010-04-30 12:15:12 +000082 # the source dir is relative to the buildir
83 srcdir = os.path.abspath(os.path.join(buildir,
84 get_config_var('srcdir')))
85 # Include is located in the srcdir
86 inc_dir = os.path.join(srcdir, "Include")
Tarek Ziadédd7bef92010-03-05 00:16:02 +000087 return inc_dir
88 return os.path.join(prefix, "include", "python" + get_python_version())
89 elif os.name == "nt":
90 return os.path.join(prefix, "include")
Tarek Ziadédd7bef92010-03-05 00:16:02 +000091 elif os.name == "os2":
92 return os.path.join(prefix, "Include")
Greg Ward7d73b9e2000-03-09 03:16:05 +000093 else:
Tarek Ziadédd7bef92010-03-05 00:16:02 +000094 raise DistutilsPlatformError(
95 "I don't know where Python installs its C header files "
96 "on platform '%s'" % os.name)
Greg Ward7d73b9e2000-03-09 03:16:05 +000097
98
Tarek Ziadédd7bef92010-03-05 00:16:02 +000099def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
100 """Return the directory containing the Python library (standard or
Fred Drakec1ee39a2000-03-09 15:54:52 +0000101 site additions).
Greg Ward7d73b9e2000-03-09 03:16:05 +0000102
Fred Drakec1ee39a2000-03-09 15:54:52 +0000103 If 'plat_specific' is true, return the directory containing
104 platform-specific modules, i.e. any module from a non-pure-Python
105 module distribution; otherwise, return the platform-shared library
106 directory. If 'standard_lib' is true, return the directory
107 containing standard Python library modules; otherwise, return the
108 directory for site-specific modules.
109
Greg Wardd38e6f72000-04-10 01:17:49 +0000110 If 'prefix' is supplied, use it instead of sys.prefix or
111 sys.exec_prefix -- i.e., ignore 'plat_specific'.
Fred Drakec1ee39a2000-03-09 15:54:52 +0000112 """
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000113 if prefix is None:
114 prefix = plat_specific and EXEC_PREFIX or PREFIX
Marc-André Lemburg2544f512002-01-31 18:56:00 +0000115
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000116 if os.name == "posix":
117 libpython = os.path.join(prefix,
118 "lib", "python" + get_python_version())
119 if standard_lib:
120 return libpython
Marc-André Lemburg2544f512002-01-31 18:56:00 +0000121 else:
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000122 return os.path.join(libpython, "site-packages")
123
124 elif os.name == "nt":
125 if standard_lib:
126 return os.path.join(prefix, "Lib")
127 else:
128 if get_python_version() < "2.2":
129 return prefix
130 else:
131 return os.path.join(prefix, "Lib", "site-packages")
132
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000133 elif os.name == "os2":
134 if standard_lib:
135 return os.path.join(prefix, "Lib")
136 else:
137 return os.path.join(prefix, "Lib", "site-packages")
138
Greg Ward7d73b9e2000-03-09 03:16:05 +0000139 else:
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000140 raise DistutilsPlatformError(
141 "I don't know where Python installs its library "
142 "on platform '%s'" % os.name)
143
Ned Deily0d0ea482012-02-10 12:59:06 +0100144_USE_CLANG = None
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000145
146def customize_compiler(compiler):
147 """Do any platform-specific customization of a CCompiler instance.
148
149 Mainly needed on Unix, so we can plug in the information that
150 varies across Unices and is stored in Python's Makefile.
151 """
152 if compiler.compiler_type == "unix":
Ned Deilyc47a4592012-02-11 20:40:24 +0100153 (cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000154 get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
Ned Deilyc47a4592012-02-11 20:40:24 +0100155 'CCSHARED', 'LDSHARED', 'SO', 'AR',
156 'ARFLAGS')
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000157
Ned Deily0d0ea482012-02-10 12:59:06 +0100158 newcc = None
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000159 if 'CC' in os.environ:
Ned Deily0d0ea482012-02-10 12:59:06 +0100160 newcc = os.environ['CC']
161 elif sys.platform == 'darwin' and cc == 'gcc-4.2':
162 # Issue #13590:
163 # Since Apple removed gcc-4.2 in Xcode 4.2, we can no
164 # longer assume it is available for extension module builds.
165 # If Python was built with gcc-4.2, check first to see if
166 # it is available on this system; if not, try to use clang
167 # instead unless the caller explicitly set CC.
168 global _USE_CLANG
169 if _USE_CLANG is None:
170 from distutils import log
171 from subprocess import Popen, PIPE
172 p = Popen("! type gcc-4.2 && type clang && exit 2",
173 shell=True, stdout=PIPE, stderr=PIPE)
174 p.wait()
175 if p.returncode == 2:
176 _USE_CLANG = True
177 log.warn("gcc-4.2 not found, using clang instead")
178 else:
179 _USE_CLANG = False
180 if _USE_CLANG:
181 newcc = 'clang'
182 if newcc:
183 # On OS X, if CC is overridden, use that as the default
184 # command for LDSHARED as well
185 if (sys.platform == 'darwin'
186 and 'LDSHARED' not in os.environ
187 and ldshared.startswith(cc)):
188 ldshared = newcc + ldshared[len(cc):]
189 cc = newcc
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000190 if 'CXX' in os.environ:
191 cxx = os.environ['CXX']
192 if 'LDSHARED' in os.environ:
193 ldshared = os.environ['LDSHARED']
194 if 'CPP' in os.environ:
195 cpp = os.environ['CPP']
Andrew M. Kuchling29c86232002-11-04 19:53:24 +0000196 else:
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000197 cpp = cc + " -E" # not always
198 if 'LDFLAGS' in os.environ:
199 ldshared = ldshared + ' ' + os.environ['LDFLAGS']
200 if 'CFLAGS' in os.environ:
201 cflags = opt + ' ' + os.environ['CFLAGS']
202 ldshared = ldshared + ' ' + os.environ['CFLAGS']
203 if 'CPPFLAGS' in os.environ:
204 cpp = cpp + ' ' + os.environ['CPPFLAGS']
205 cflags = cflags + ' ' + os.environ['CPPFLAGS']
206 ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
Ned Deilyc47a4592012-02-11 20:40:24 +0100207 if 'AR' in os.environ:
208 ar = os.environ['AR']
209 if 'ARFLAGS' in os.environ:
210 archiver = ar + ' ' + os.environ['ARFLAGS']
211 else:
212 archiver = ar + ' ' + ar_flags
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000213
214 cc_cmd = cc + ' ' + cflags
215 compiler.set_executables(
216 preprocessor=cpp,
217 compiler=cc_cmd,
218 compiler_so=cc_cmd + ' ' + ccshared,
219 compiler_cxx=cxx,
220 linker_so=ldshared,
Ned Deilyc47a4592012-02-11 20:40:24 +0100221 linker_exe=cc,
222 archiver=archiver)
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000223
224 compiler.shared_lib_extension = so_ext
225
226
227def get_config_h_filename():
228 """Return full pathname of installed pyconfig.h file."""
229 if python_build:
230 if os.name == "nt":
231 inc_dir = os.path.join(project_base, "PC")
232 else:
233 inc_dir = project_base
234 else:
235 inc_dir = get_python_inc(plat_specific=1)
236 if get_python_version() < '2.2':
237 config_h = 'config.h'
238 else:
239 # The name of the config.h file changed in 2.2
240 config_h = 'pyconfig.h'
241 return os.path.join(inc_dir, config_h)
242
Greg Ward1190ee31998-12-18 23:46:33 +0000243
Greg Ward9ddaaa11999-01-06 14:46:06 +0000244def get_makefile_filename():
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000245 """Return full pathname of installed Makefile from the Python build."""
246 if python_build:
247 return os.path.join(os.path.dirname(sys.executable), "Makefile")
248 lib_dir = get_python_lib(plat_specific=1, standard_lib=1)
249 return os.path.join(lib_dir, "config", "Makefile")
Greg Ward7d73b9e2000-03-09 03:16:05 +0000250
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000251
252def parse_config_h(fp, g=None):
253 """Parse a config.h-style file.
254
255 A dictionary containing name/value pairs is returned. If an
256 optional dictionary is passed in as the second argument, it is
257 used instead of a new dictionary.
Fred Drake522af3a1999-01-06 16:28:34 +0000258 """
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000259 if g is None:
260 g = {}
261 define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
262 undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
263 #
264 while 1:
265 line = fp.readline()
266 if not line:
267 break
268 m = define_rx.match(line)
269 if m:
270 n, v = m.group(1, 2)
271 try: v = int(v)
272 except ValueError: pass
273 g[n] = v
274 else:
275 m = undef_rx.match(line)
276 if m:
277 g[m.group(1)] = 0
278 return g
279
Greg Wardd283ce72000-09-17 00:53:02 +0000280
281# Regexes needed for parsing Makefile (and similar syntaxes,
282# like old-style Setup files).
283_variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)")
284_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)")
285_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}")
286
Greg Ward3fff8d22000-09-15 00:03:13 +0000287def parse_makefile(fn, g=None):
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000288 """Parse a Makefile-style file.
Fred Drakec1ee39a2000-03-09 15:54:52 +0000289
290 A dictionary containing name/value pairs is returned. If an
291 optional dictionary is passed in as the second argument, it is
292 used instead of a new dictionary.
Fred Drake522af3a1999-01-06 16:28:34 +0000293 """
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000294 from distutils.text_file import TextFile
295 fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1)
296
297 if g is None:
298 g = {}
299 done = {}
300 notdone = {}
301
302 while 1:
303 line = fp.readline()
304 if line is None: # eof
305 break
306 m = _variable_rx.match(line)
307 if m:
308 n, v = m.group(1, 2)
309 v = v.strip()
310 # `$$' is a literal `$' in make
311 tmpv = v.replace('$$', '')
312
313 if "$" in tmpv:
314 notdone[n] = v
315 else:
316 try:
317 v = int(v)
318 except ValueError:
319 # insert literal `$'
320 done[n] = v.replace('$$', '$')
321 else:
322 done[n] = v
323
324 # do variable interpolation here
325 while notdone:
326 for name in notdone.keys():
327 value = notdone[name]
328 m = _findvar1_rx.search(value) or _findvar2_rx.search(value)
329 if m:
330 n = m.group(1)
331 found = True
332 if n in done:
333 item = str(done[n])
334 elif n in notdone:
335 # get it on a subsequent round
336 found = False
337 elif n in os.environ:
338 # do it like make: fall back to environment
339 item = os.environ[n]
340 else:
341 done[n] = item = ""
342 if found:
343 after = value[m.end():]
344 value = value[:m.start()] + item + after
345 if "$" in after:
346 notdone[name] = value
347 else:
348 try: value = int(value)
349 except ValueError:
350 done[name] = value.strip()
351 else:
352 done[name] = value
353 del notdone[name]
354 else:
355 # bogus variable reference; just drop it since we can't deal
356 del notdone[name]
357
358 fp.close()
359
Antoine Pitrou58dab672010-10-10 09:54:59 +0000360 # strip spurious spaces
361 for k, v in done.items():
362 if isinstance(v, str):
363 done[k] = v.strip()
364
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000365 # save the results in the global dictionary
366 g.update(done)
367 return g
368
Greg Ward1190ee31998-12-18 23:46:33 +0000369
Greg Wardd283ce72000-09-17 00:53:02 +0000370def expand_makefile_vars(s, vars):
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000371 """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in
Greg Wardd283ce72000-09-17 00:53:02 +0000372 'string' according to 'vars' (a dictionary mapping variable names to
373 values). Variables not present in 'vars' are silently expanded to the
374 empty string. The variable values in 'vars' should not contain further
375 variable expansions; if 'vars' is the output of 'parse_makefile()',
376 you're fine. Returns a variable-expanded version of 's'.
377 """
378
379 # This algorithm does multiple expansion, so if vars['foo'] contains
380 # "${bar}", it will expand ${foo} to ${bar}, and then expand
381 # ${bar}... and so forth. This is fine as long as 'vars' comes from
382 # 'parse_makefile()', which takes care of such expansions eagerly,
383 # according to make's variable expansion semantics.
384
385 while 1:
386 m = _findvar1_rx.search(s) or _findvar2_rx.search(s)
387 if m:
Greg Wardd283ce72000-09-17 00:53:02 +0000388 (beg, end) = m.span()
389 s = s[0:beg] + vars.get(m.group(1)) + s[end:]
390 else:
391 break
392 return s
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000393
394
395_config_vars = None
396
397def _init_posix():
398 """Initialize the module as appropriate for POSIX systems."""
399 g = {}
400 # load the installed Makefile:
401 try:
402 filename = get_makefile_filename()
403 parse_makefile(filename, g)
404 except IOError, msg:
405 my_msg = "invalid Python installation: unable to open %s" % filename
406 if hasattr(msg, "strerror"):
407 my_msg = my_msg + " (%s)" % msg.strerror
408
409 raise DistutilsPlatformError(my_msg)
410
411 # load the installed pyconfig.h:
412 try:
413 filename = get_config_h_filename()
414 parse_config_h(file(filename), g)
415 except IOError, msg:
416 my_msg = "invalid Python installation: unable to open %s" % filename
417 if hasattr(msg, "strerror"):
418 my_msg = my_msg + " (%s)" % msg.strerror
419
420 raise DistutilsPlatformError(my_msg)
421
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000422 # On AIX, there are wrong paths to the linker scripts in the Makefile
423 # -- these paths are relative to the Python source, but when installed
424 # the scripts are in another directory.
425 if python_build:
426 g['LDSHARED'] = g['BLDSHARED']
427
428 elif get_python_version() < '2.1':
429 # The following two branches are for 1.5.2 compatibility.
430 if sys.platform == 'aix4': # what about AIX 3.x ?
431 # Linker script is in the config directory, not in Modules as the
432 # Makefile says.
433 python_lib = get_python_lib(standard_lib=1)
434 ld_so_aix = os.path.join(python_lib, 'config', 'ld_so_aix')
435 python_exp = os.path.join(python_lib, 'config', 'python.exp')
436
437 g['LDSHARED'] = "%s %s -bI:%s" % (ld_so_aix, g['CC'], python_exp)
438
439 elif sys.platform == 'beos':
440 # Linker script is in the config directory. In the Makefile it is
441 # relative to the srcdir, which after installation no longer makes
442 # sense.
443 python_lib = get_python_lib(standard_lib=1)
444 linkerscript_path = string.split(g['LDSHARED'])[0]
445 linkerscript_name = os.path.basename(linkerscript_path)
446 linkerscript = os.path.join(python_lib, 'config',
447 linkerscript_name)
448
449 # XXX this isn't the right place to do this: adding the Python
450 # library to the link, if needed, should be in the "build_ext"
451 # command. (It's also needed for non-MS compilers on Windows, and
452 # it's taken care of for them by the 'build_ext.get_libraries()'
453 # method.)
454 g['LDSHARED'] = ("%s -L%s/lib -lpython%s" %
455 (linkerscript, PREFIX, get_python_version()))
456
457 global _config_vars
458 _config_vars = g
459
460
461def _init_nt():
462 """Initialize the module as appropriate for NT"""
463 g = {}
464 # set basic install directories
465 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
466 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
467
468 # XXX hmmm.. a normal install puts include files here
469 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
470
471 g['SO'] = '.pyd'
472 g['EXE'] = ".exe"
473 g['VERSION'] = get_python_version().replace(".", "")
474 g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
475
476 global _config_vars
477 _config_vars = g
478
479
Tarek Ziadédd7bef92010-03-05 00:16:02 +0000480def _init_os2():
481 """Initialize the module as appropriate for OS/2"""
482 g = {}
483 # set basic install directories
484 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
485 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
486
487 # XXX hmmm.. a normal install puts include files here
488 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
489
490 g['SO'] = '.pyd'
491 g['EXE'] = ".exe"
492
493 global _config_vars
494 _config_vars = g
495
496
497def get_config_vars(*args):
498 """With no arguments, return a dictionary of all configuration
499 variables relevant for the current platform. Generally this includes
500 everything needed to build extensions and install both pure modules and
501 extensions. On Unix, this means every variable defined in Python's
502 installed Makefile; on Windows and Mac OS it's a much smaller set.
503
504 With arguments, return a list of values that result from looking up
505 each argument in the configuration variable dictionary.
506 """
507 global _config_vars
508 if _config_vars is None:
509 func = globals().get("_init_" + os.name)
510 if func:
511 func()
512 else:
513 _config_vars = {}
514
515 # Normalized versions of prefix and exec_prefix are handy to have;
516 # in fact, these are the standard versions used most places in the
517 # Distutils.
518 _config_vars['prefix'] = PREFIX
519 _config_vars['exec_prefix'] = EXEC_PREFIX
520
521 if sys.platform == 'darwin':
522 kernel_version = os.uname()[2] # Kernel version (8.4.3)
523 major_version = int(kernel_version.split('.')[0])
524
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', 'LDSHARED',
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)
536 flags = re.sub('-isysroot [^ \t]*', ' ', flags)
537 _config_vars[key] = flags
538
539 else:
540
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
545 # that OS release.
546
547 if 'ARCHFLAGS' in os.environ:
548 arch = os.environ['ARCHFLAGS']
549 for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
550 # a number of derived variables. These need to be
551 # patched up as well.
552 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
553
554 flags = _config_vars[key]
555 flags = re.sub('-arch\s+\w+\s', ' ', flags)
556 flags = flags + ' ' + arch
557 _config_vars[key] = flags
558
559 # If we're on OSX 10.5 or later and the user tries to
560 # compiles an extension using an SDK that is not present
561 # on the current machine it is better to not use an SDK
562 # than to fail.
563 #
564 # The major usecase for this is users using a Python.org
565 # binary installer on OSX 10.6: that installer uses
566 # the 10.4u SDK, but that SDK is not installed by default
567 # when you install Xcode.
568 #
569 m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS'])
570 if m is not None:
571 sdk = m.group(1)
572 if not os.path.exists(sdk):
573 for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
574 # a number of derived variables. These need to be
575 # patched up as well.
576 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
577
578 flags = _config_vars[key]
579 flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
580 _config_vars[key] = flags
581
582 if args:
583 vals = []
584 for name in args:
585 vals.append(_config_vars.get(name))
586 return vals
587 else:
588 return _config_vars
589
590def get_config_var(name):
591 """Return the value of a single variable using the dictionary
592 returned by 'get_config_vars()'. Equivalent to
593 get_config_vars().get(name)
594 """
595 return get_config_vars().get(name)