summaryrefslogtreecommitdiff
path: root/Lib/distutils/sysconfig.py
diff options
context:
space:
mode:
authorNed Deily <nad@acm.org>2012-06-23 16:02:19 -0700
committerNed Deily <nad@acm.org>2012-06-23 16:02:19 -0700
commit07020e7ceee1fc8cd6bd07901839f4c39e77b226 (patch)
tree640027984b8a78649e45ef902a50a9385b0ec52e /Lib/distutils/sysconfig.py
parent350ce0ff79836330ca167da28e618027769da9c9 (diff)
downloadcpython-07020e7ceee1fc8cd6bd07901839f4c39e77b226.tar.gz
Issue #13590: Improve support for OS X Xcode 4:
- Try to avoid building Python or extension modules with problematic llvm-gcc compiler. - Since Xcode 4 removes ppc support, extension module builds now check for ppc compiler support and automatically remove ppc and ppc64 archs when not available. - Since Xcode 4 no longer install SDKs in default locations, extension module builds now revert to using installed headers and libs if the SDK used to build the interpreter is not available. - Update ./configure to use better defaults for universal builds; in particular, --enable-universalsdk=yes uses the Xcode default SDK and --with-universal-archs now defaults to "intel" if ppc not available.
Diffstat (limited to 'Lib/distutils/sysconfig.py')
-rw-r--r--Lib/distutils/sysconfig.py147
1 files changed, 114 insertions, 33 deletions
diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py
index e86cb23236..dac3035f1b 100644
--- a/Lib/distutils/sysconfig.py
+++ b/Lib/distutils/sysconfig.py
@@ -162,7 +162,7 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
"I don't know where Python installs its library "
"on platform '%s'" % os.name)
-_USE_CLANG = None
+
def customize_compiler(compiler):
"""Do any platform-specific customization of a CCompiler instance.
@@ -177,36 +177,7 @@ def customize_compiler(compiler):
newcc = None
if 'CC' in os.environ:
- newcc = os.environ['CC']
- elif sys.platform == 'darwin' and cc == 'gcc-4.2':
- # Issue #13590:
- # Since Apple removed gcc-4.2 in Xcode 4.2, we can no
- # longer assume it is available for extension module builds.
- # If Python was built with gcc-4.2, check first to see if
- # it is available on this system; if not, try to use clang
- # instead unless the caller explicitly set CC.
- global _USE_CLANG
- if _USE_CLANG is None:
- from distutils import log
- from subprocess import Popen, PIPE
- p = Popen("! type gcc-4.2 && type clang && exit 2",
- shell=True, stdout=PIPE, stderr=PIPE)
- p.wait()
- if p.returncode == 2:
- _USE_CLANG = True
- log.warn("gcc-4.2 not found, using clang instead")
- else:
- _USE_CLANG = False
- if _USE_CLANG:
- newcc = 'clang'
- if newcc:
- # On OS X, if CC is overridden, use that as the default
- # command for LDSHARED as well
- if (sys.platform == 'darwin'
- and 'LDSHARED' not in os.environ
- and ldshared.startswith(cc)):
- ldshared = newcc + ldshared[len(cc):]
- cc = newcc
+ cc = os.environ['CC']
if 'CXX' in os.environ:
cxx = os.environ['CXX']
if 'LDSHARED' in os.environ:
@@ -522,6 +493,29 @@ def _init_os2():
_config_vars = g
+def _read_output(commandstring):
+ """
+ Returns os.popen(commandstring, "r").read(), but
+ without actually using os.popen because that
+ function is not usable during python bootstrap
+ """
+ # NOTE: tempfile is also not useable during
+ # bootstrap
+ import contextlib
+ try:
+ import tempfile
+ fp = tempfile.NamedTemporaryFile()
+ except ImportError:
+ fp = open("/tmp/distutils.%s"%(
+ os.getpid(),), "w+b")
+
+ with contextlib.closing(fp) as fp:
+ cmd = "%s >'%s'"%(commandstring, fp.name)
+ os.system(cmd)
+ data = fp.read()
+
+ return data.decode('utf-8')
+
def get_config_vars(*args):
"""With no arguments, return a dictionary of all configuration
variables relevant for the current platform. Generally this includes
@@ -561,9 +555,70 @@ def get_config_vars(*args):
_config_vars['srcdir'] = os.path.normpath(srcdir)
if sys.platform == 'darwin':
+ from distutils.spawn import find_executable
+
kernel_version = os.uname()[2] # Kernel version (8.4.3)
major_version = int(kernel_version.split('.')[0])
+ # Issue #13590:
+ # The OSX location for the compiler varies between OSX
+ # (or rather Xcode) releases. With older releases (up-to 10.5)
+ # the compiler is in /usr/bin, with newer releases the compiler
+ # can only be found inside Xcode.app if the "Command Line Tools"
+ # are not installed.
+ #
+ # Futhermore, the compiler that can be used varies between
+ # Xcode releases. Upto Xcode 4 it was possible to use 'gcc-4.2'
+ # as the compiler, after that 'clang' should be used because
+ # gcc-4.2 is either not present, or a copy of 'llvm-gcc' that
+ # miscompiles Python.
+
+ # skip checks if the compiler was overriden with a CC env variable
+ if 'CC' not in os.environ:
+ cc = oldcc = _config_vars['CC']
+ if not find_executable(cc):
+ # Compiler is not found on the shell search PATH.
+ # Now search for clang, first on PATH (if the Command LIne
+ # Tools have been installed in / or if the user has provided
+ # another location via CC). If not found, try using xcrun
+ # to find an uninstalled clang (within a selected Xcode).
+
+ # NOTE: Cannot use subprocess here because of bootstrap
+ # issues when building Python itself (and os.popen is
+ # implemented on top of subprocess and is therefore not
+ # usable as well)
+
+ data = (find_executable('clang') or
+ _read_output(
+ "/usr/bin/xcrun -find clang 2>/dev/null").strip())
+ if not data:
+ raise DistutilsPlatformError(
+ "Cannot locate working compiler")
+
+ _config_vars['CC'] = cc = data
+ _config_vars['CXX'] = cc + '++'
+
+ elif os.path.basename(cc).startswith('gcc'):
+ # Compiler is GCC, check if it is LLVM-GCC
+ data = _read_output("'%s' --version 2>/dev/null"
+ % (cc.replace("'", "'\"'\"'"),))
+ if 'llvm-gcc' in data:
+ # Found LLVM-GCC, fall back to clang
+ data = (find_executable('clang') or
+ _read_output(
+ "/usr/bin/xcrun -find clang 2>/dev/null").strip())
+ if find_executable(data):
+ _config_vars['CC'] = cc = data
+ _config_vars['CXX'] = cc + '++'
+
+ if (cc != oldcc
+ and 'LDSHARED' in _config_vars
+ and 'LDSHARED' not in os.environ):
+ # modify LDSHARED if we modified CC
+ ldshared = _config_vars['LDSHARED']
+ if ldshared.startswith(oldcc):
+ _config_vars['LDSHARED'] = cc + ldshared[len(oldcc):]
+
if major_version < 8:
# On Mac OS X before 10.4, check if -arch and -isysroot
# are in CFLAGS or LDFLAGS and remove them if they are.
@@ -579,19 +634,45 @@ def get_config_vars(*args):
_config_vars[key] = flags
else:
+ # Different Xcode releases support different sets for '-arch'
+ # flags. In particular, Xcode 4.x no longer supports the
+ # PPC architectures.
+ #
+ # This code automatically removes '-arch ppc' and '-arch ppc64'
+ # when these are not supported. That makes it possible to
+ # build extensions on OSX 10.7 and later with the prebuilt
+ # 32-bit installer on the python.org website.
+ flags = _config_vars['CFLAGS']
+ if re.search('-arch\s+ppc', flags) is not None:
+ # NOTE: Cannot use subprocess here because of bootstrap
+ # issues when building Python itself
+ status = os.system("'%s' -arch ppc -x c /dev/null 2>/dev/null"%(
+ _config_vars['CC'].replace("'", "'\"'\"'"),))
+
+ if status != 0:
+ # Compiler doesn't support PPC, remove the related
+ # '-arch' flags.
+ for key in ('LDFLAGS', 'BASECFLAGS',
+ # a number of derived variables. These need to be
+ # patched up as well.
+ 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED', 'LDSHARED'):
+
+ flags = _config_vars[key]
+ flags = re.sub('-arch\s+ppc\w*\s', ' ', flags)
+ _config_vars[key] = flags
+
# Allow the user to override the architecture flags using
# an environment variable.
# NOTE: This name was introduced by Apple in OSX 10.5 and
# is used by several scripting languages distributed with
# that OS release.
-
if 'ARCHFLAGS' in os.environ:
arch = os.environ['ARCHFLAGS']
for key in ('LDFLAGS', 'BASECFLAGS',
# a number of derived variables. These need to be
# patched up as well.
- 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
+ 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED', 'LDSHARED'):
flags = _config_vars[key]
flags = re.sub('-arch\s+\w+\s', ' ', flags)