mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
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.
This commit is contained in:
parent
88bc0d2640
commit
cbfb9a56e6
5 changed files with 493 additions and 172 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue