Issue #15184: Ensure consistent results of OS X configuration
tailoring for universal builds by factoring out common OS X-specific customizations from sysconfig, distutils.sysconfig, distutils.util, and distutils.unixccompiler into a new module _osx_support that can eventually also be used by packaging.
This commit is contained in:
parent
0fd1062a76
commit
df8aa2b325
|
@ -0,0 +1,488 @@
|
||||||
|
"""Shared OS X support functions."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'compiler_fixup',
|
||||||
|
'customize_config_vars',
|
||||||
|
'customize_compiler',
|
||||||
|
'get_platform_osx',
|
||||||
|
]
|
||||||
|
|
||||||
|
# configuration variables that may contain universal build flags,
|
||||||
|
# like "-arch" or "-isdkroot", that may need customization for
|
||||||
|
# the user environment
|
||||||
|
_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS',
|
||||||
|
'BLDSHARED', 'LDSHARED', 'CC', 'CXX',
|
||||||
|
'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
|
||||||
|
'PY_CORE_CFLAGS')
|
||||||
|
|
||||||
|
# configuration variables that may contain compiler calls
|
||||||
|
_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX')
|
||||||
|
|
||||||
|
# prefix added to original configuration variable names
|
||||||
|
_INITPRE = '_OSX_SUPPORT_INITIAL_'
|
||||||
|
|
||||||
|
|
||||||
|
def _find_executable(executable, path=None):
|
||||||
|
"""Tries to find 'executable' in the directories listed in 'path'.
|
||||||
|
|
||||||
|
A string listing directories separated by 'os.pathsep'; defaults to
|
||||||
|
os.environ['PATH']. Returns the complete filename or None if not found.
|
||||||
|
"""
|
||||||
|
if path is None:
|
||||||
|
path = os.environ['PATH']
|
||||||
|
|
||||||
|
paths = path.split(os.pathsep)
|
||||||
|
base, ext = os.path.splitext(executable)
|
||||||
|
|
||||||
|
if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'):
|
||||||
|
executable = executable + '.exe'
|
||||||
|
|
||||||
|
if not os.path.isfile(executable):
|
||||||
|
for p in paths:
|
||||||
|
f = os.path.join(p, executable)
|
||||||
|
if os.path.isfile(f):
|
||||||
|
# the file exists, we have a shot at spawn working
|
||||||
|
return f
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return executable
|
||||||
|
|
||||||
|
|
||||||
|
def _read_output(commandstring):
|
||||||
|
"""Output from succesful command execution or None"""
|
||||||
|
# Similar to os.popen(commandstring, "r").read(),
|
||||||
|
# but without actually using os.popen because that
|
||||||
|
# function is not usable during python bootstrap.
|
||||||
|
# tempfile is also not available then.
|
||||||
|
import contextlib
|
||||||
|
try:
|
||||||
|
import tempfile
|
||||||
|
fp = tempfile.NamedTemporaryFile()
|
||||||
|
except ImportError:
|
||||||
|
fp = open("/tmp/_osx_support.%s"%(
|
||||||
|
os.getpid(),), "w+b")
|
||||||
|
|
||||||
|
with contextlib.closing(fp) as fp:
|
||||||
|
cmd = "%s 2>/dev/null >'%s'" % (commandstring, fp.name)
|
||||||
|
return fp.read().decode('utf-8').strip() if not os.system(cmd) else None
|
||||||
|
|
||||||
|
|
||||||
|
def _find_build_tool(toolname):
|
||||||
|
"""Find a build tool on current path or using xcrun"""
|
||||||
|
return (_find_executable(toolname)
|
||||||
|
or _read_output("/usr/bin/xcrun -find %s" % (toolname,))
|
||||||
|
or ''
|
||||||
|
)
|
||||||
|
|
||||||
|
_SYSTEM_VERSION = None
|
||||||
|
|
||||||
|
def _get_system_version():
|
||||||
|
"""Return the OS X system version as a string"""
|
||||||
|
# Reading this plist is a documented way to get the system
|
||||||
|
# version (see the documentation for the Gestalt Manager)
|
||||||
|
# We avoid using platform.mac_ver to avoid possible bootstrap issues during
|
||||||
|
# the build of Python itself (distutils is used to build standard library
|
||||||
|
# extensions).
|
||||||
|
|
||||||
|
global _SYSTEM_VERSION
|
||||||
|
|
||||||
|
if _SYSTEM_VERSION is None:
|
||||||
|
_SYSTEM_VERSION = ''
|
||||||
|
try:
|
||||||
|
f = open('/System/Library/CoreServices/SystemVersion.plist')
|
||||||
|
except IOError:
|
||||||
|
# We're on a plain darwin box, fall back to the default
|
||||||
|
# behaviour.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
|
||||||
|
r'<string>(.*?)</string>', f.read())
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
if m is not None:
|
||||||
|
_SYSTEM_VERSION = '.'.join(m.group(1).split('.')[:2])
|
||||||
|
# else: fall back to the default behaviour
|
||||||
|
|
||||||
|
return _SYSTEM_VERSION
|
||||||
|
|
||||||
|
def _remove_original_values(_config_vars):
|
||||||
|
"""Remove original unmodified values for testing"""
|
||||||
|
# This is needed for higher-level cross-platform tests of get_platform.
|
||||||
|
for k in list(_config_vars):
|
||||||
|
if k.startswith(_INITPRE):
|
||||||
|
del _config_vars[k]
|
||||||
|
|
||||||
|
def _save_modified_value(_config_vars, cv, newvalue):
|
||||||
|
"""Save modified and original unmodified value of configuration var"""
|
||||||
|
|
||||||
|
oldvalue = _config_vars.get(cv, '')
|
||||||
|
if (oldvalue != newvalue) and (_INITPRE + cv not in _config_vars):
|
||||||
|
_config_vars[_INITPRE + cv] = oldvalue
|
||||||
|
_config_vars[cv] = newvalue
|
||||||
|
|
||||||
|
def _supports_universal_builds():
|
||||||
|
"""Returns True if universal builds are supported on this system"""
|
||||||
|
# As an approximation, we assume that if we are running on 10.4 or above,
|
||||||
|
# then we are running with an Xcode environment that supports universal
|
||||||
|
# builds, in particular -isysroot and -arch arguments to the compiler. This
|
||||||
|
# is in support of allowing 10.4 universal builds to run on 10.3.x systems.
|
||||||
|
|
||||||
|
osx_version = _get_system_version()
|
||||||
|
if osx_version:
|
||||||
|
try:
|
||||||
|
osx_version = tuple(int(i) for i in osx_version.split('.'))
|
||||||
|
except ValueError:
|
||||||
|
osx_version = ''
|
||||||
|
return bool(osx_version >= (10, 4)) if osx_version else False
|
||||||
|
|
||||||
|
|
||||||
|
def _find_appropriate_compiler(_config_vars):
|
||||||
|
"""Find appropriate C compiler for extension module builds"""
|
||||||
|
|
||||||
|
# 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' in os.environ:
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
# The CC config var might contain additional arguments.
|
||||||
|
# Ignore them while searching.
|
||||||
|
cc = oldcc = _config_vars['CC'].split()[0]
|
||||||
|
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)
|
||||||
|
|
||||||
|
cc = _find_build_tool('clang')
|
||||||
|
|
||||||
|
elif os.path.basename(cc).startswith('gcc'):
|
||||||
|
# Compiler is GCC, check if it is LLVM-GCC
|
||||||
|
data = _read_output("'%s' --version"
|
||||||
|
% (cc.replace("'", "'\"'\"'"),))
|
||||||
|
if 'llvm-gcc' in data:
|
||||||
|
# Found LLVM-GCC, fall back to clang
|
||||||
|
cc = _find_build_tool('clang')
|
||||||
|
|
||||||
|
if not cc:
|
||||||
|
raise SystemError(
|
||||||
|
"Cannot locate working compiler")
|
||||||
|
|
||||||
|
if cc != oldcc:
|
||||||
|
# Found a replacement compiler.
|
||||||
|
# Modify config vars using new compiler, if not already explictly
|
||||||
|
# overriden by an env variable, preserving additional arguments.
|
||||||
|
for cv in _COMPILER_CONFIG_VARS:
|
||||||
|
if cv in _config_vars and cv not in os.environ:
|
||||||
|
cv_split = _config_vars[cv].split()
|
||||||
|
cv_split[0] = cc if cv != 'CXX' else cc + '++'
|
||||||
|
_save_modified_value(_config_vars, cv, ' '.join(cv_split))
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_universal_flags(_config_vars):
|
||||||
|
"""Remove all universal build arguments from config vars"""
|
||||||
|
|
||||||
|
for cv in _UNIVERSAL_CONFIG_VARS:
|
||||||
|
# Do not alter a config var explicitly overriden by env var
|
||||||
|
if cv in _config_vars and cv not in os.environ:
|
||||||
|
flags = _config_vars[cv]
|
||||||
|
flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
|
||||||
|
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
|
||||||
|
_save_modified_value(_config_vars, cv, flags)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_unsupported_archs(_config_vars):
|
||||||
|
"""Remove any unsupported archs from config vars"""
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# skip checks if the compiler was overriden with a CC env variable
|
||||||
|
if 'CC' in os.environ:
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
if re.search('-arch\s+ppc', _config_vars['CFLAGS']) 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("'", "'\"'\"'"),))
|
||||||
|
# The Apple compiler drivers return status 255 if no PPC
|
||||||
|
if (status >> 8) == 255:
|
||||||
|
# Compiler doesn't support PPC, remove the related
|
||||||
|
# '-arch' flags if not explicitly overridden by an
|
||||||
|
# environment variable
|
||||||
|
for cv in _UNIVERSAL_CONFIG_VARS:
|
||||||
|
if cv in _config_vars and cv not in os.environ:
|
||||||
|
flags = _config_vars[cv]
|
||||||
|
flags = re.sub('-arch\s+ppc\w*\s', ' ', flags)
|
||||||
|
_save_modified_value(_config_vars, cv, flags)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def _override_all_archs(_config_vars):
|
||||||
|
"""Allow override of all archs with ARCHFLAGS env var"""
|
||||||
|
# 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 cv in _UNIVERSAL_CONFIG_VARS:
|
||||||
|
if cv in _config_vars and '-arch' in _config_vars[cv]:
|
||||||
|
flags = _config_vars[cv]
|
||||||
|
flags = re.sub('-arch\s+\w+\s', ' ', flags)
|
||||||
|
flags = flags + ' ' + arch
|
||||||
|
_save_modified_value(_config_vars, cv, flags)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def _check_for_unavailable_sdk(_config_vars):
|
||||||
|
"""Remove references to any SDKs not available"""
|
||||||
|
# If we're on OSX 10.5 or later and the user tries to
|
||||||
|
# compile an extension using an SDK that is not present
|
||||||
|
# on the current machine it is better to not use an SDK
|
||||||
|
# than to fail. This is particularly important with
|
||||||
|
# the standalong Command Line Tools alternative to a
|
||||||
|
# full-blown Xcode install since the CLT packages do not
|
||||||
|
# provide SDKs. If the SDK is not present, it is assumed
|
||||||
|
# that the header files and dev libs have been installed
|
||||||
|
# to /usr and /System/Library by either a standalone CLT
|
||||||
|
# package or the CLT component within Xcode.
|
||||||
|
cflags = _config_vars.get('CFLAGS', '')
|
||||||
|
m = re.search(r'-isysroot\s+(\S+)', cflags)
|
||||||
|
if m is not None:
|
||||||
|
sdk = m.group(1)
|
||||||
|
if not os.path.exists(sdk):
|
||||||
|
for cv in _UNIVERSAL_CONFIG_VARS:
|
||||||
|
# Do not alter a config var explicitly overriden by env var
|
||||||
|
if cv in _config_vars and cv not in os.environ:
|
||||||
|
flags = _config_vars[cv]
|
||||||
|
flags = re.sub(r'-isysroot\s+\S+(?:\s|$)', ' ', flags)
|
||||||
|
_save_modified_value(_config_vars, cv, flags)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def compiler_fixup(compiler_so, cc_args):
|
||||||
|
"""
|
||||||
|
This function will strip '-isysroot PATH' and '-arch ARCH' from the
|
||||||
|
compile flags if the user has specified one them in extra_compile_flags.
|
||||||
|
|
||||||
|
This is needed because '-arch ARCH' adds another architecture to the
|
||||||
|
build, without a way to remove an architecture. Furthermore GCC will
|
||||||
|
barf if multiple '-isysroot' arguments are present.
|
||||||
|
"""
|
||||||
|
stripArch = stripSysroot = False
|
||||||
|
|
||||||
|
compiler_so = list(compiler_so)
|
||||||
|
|
||||||
|
if not _supports_universal_builds():
|
||||||
|
# OSX before 10.4.0, these don't support -arch and -isysroot at
|
||||||
|
# all.
|
||||||
|
stripArch = stripSysroot = True
|
||||||
|
else:
|
||||||
|
stripArch = '-arch' in cc_args
|
||||||
|
stripSysroot = '-isysroot' in cc_args
|
||||||
|
|
||||||
|
if stripArch or 'ARCHFLAGS' in os.environ:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
index = compiler_so.index('-arch')
|
||||||
|
# Strip this argument and the next one:
|
||||||
|
del compiler_so[index:index+2]
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
|
||||||
|
if 'ARCHFLAGS' in os.environ and not stripArch:
|
||||||
|
# User specified different -arch flags in the environ,
|
||||||
|
# see also distutils.sysconfig
|
||||||
|
compiler_so = compiler_so + os.environ['ARCHFLAGS'].split()
|
||||||
|
|
||||||
|
if stripSysroot:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
index = compiler_so.index('-isysroot')
|
||||||
|
# Strip this argument and the next one:
|
||||||
|
del compiler_so[index:index+2]
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Check if the SDK that is used during compilation actually exists,
|
||||||
|
# the universal build requires the usage of a universal SDK and not all
|
||||||
|
# users have that installed by default.
|
||||||
|
sysroot = None
|
||||||
|
if '-isysroot' in cc_args:
|
||||||
|
idx = cc_args.index('-isysroot')
|
||||||
|
sysroot = cc_args[idx+1]
|
||||||
|
elif '-isysroot' in compiler_so:
|
||||||
|
idx = compiler_so.index('-isysroot')
|
||||||
|
sysroot = compiler_so[idx+1]
|
||||||
|
|
||||||
|
if sysroot and not os.path.isdir(sysroot):
|
||||||
|
from distutils import log
|
||||||
|
log.warn("Compiling with an SDK that doesn't seem to exist: %s",
|
||||||
|
sysroot)
|
||||||
|
log.warn("Please check your Xcode installation")
|
||||||
|
|
||||||
|
return compiler_so
|
||||||
|
|
||||||
|
|
||||||
|
def customize_config_vars(_config_vars):
|
||||||
|
"""Customize Python build configuration variables.
|
||||||
|
|
||||||
|
Called internally from sysconfig with a mutable mapping
|
||||||
|
containing name/value pairs parsed from the configured
|
||||||
|
makefile used to build this interpreter. Returns
|
||||||
|
the mapping updated as needed to reflect the environment
|
||||||
|
in which the interpreter is running; in the case of
|
||||||
|
a Python from a binary installer, the installed
|
||||||
|
environment may be very different from the build
|
||||||
|
environment, i.e. different OS levels, different
|
||||||
|
built tools, different available CPU architectures.
|
||||||
|
|
||||||
|
This customization is performed whenever
|
||||||
|
distutils.sysconfig.get_config_vars() is first
|
||||||
|
called. It may be used in environments where no
|
||||||
|
compilers are present, i.e. when installing pure
|
||||||
|
Python dists. Customization of compiler paths
|
||||||
|
and detection of unavailable archs is deferred
|
||||||
|
until the first extention module build is
|
||||||
|
requested (in distutils.sysconfig.customize_compiler).
|
||||||
|
|
||||||
|
Currently called from distutils.sysconfig
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not _supports_universal_builds():
|
||||||
|
# On Mac OS X before 10.4, check if -arch and -isysroot
|
||||||
|
# are in CFLAGS or LDFLAGS and remove them if they are.
|
||||||
|
# This is needed when building extensions on a 10.3 system
|
||||||
|
# using a universal build of python.
|
||||||
|
_remove_universal_flags(_config_vars)
|
||||||
|
|
||||||
|
# Allow user to override all archs with ARCHFLAGS env var
|
||||||
|
_override_all_archs(_config_vars)
|
||||||
|
|
||||||
|
# Remove references to sdks that are not found
|
||||||
|
_check_for_unavailable_sdk(_config_vars)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def customize_compiler(_config_vars):
|
||||||
|
"""Customize compiler path and configuration variables.
|
||||||
|
|
||||||
|
This customization is performed when the first
|
||||||
|
extension module build is requested
|
||||||
|
in distutils.sysconfig.customize_compiler).
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Find a compiler to use for extension module builds
|
||||||
|
_find_appropriate_compiler(_config_vars)
|
||||||
|
|
||||||
|
# Remove ppc arch flags if not supported here
|
||||||
|
_remove_unsupported_archs(_config_vars)
|
||||||
|
|
||||||
|
# Allow user to override all archs with ARCHFLAGS env var
|
||||||
|
_override_all_archs(_config_vars)
|
||||||
|
|
||||||
|
return _config_vars
|
||||||
|
|
||||||
|
|
||||||
|
def get_platform_osx(_config_vars, osname, release, machine):
|
||||||
|
"""Filter values for get_platform()"""
|
||||||
|
# called from get_platform() in sysconfig and distutils.util
|
||||||
|
#
|
||||||
|
# For our purposes, we'll assume that the system version from
|
||||||
|
# distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
|
||||||
|
# to. This makes the compatibility story a bit more sane because the
|
||||||
|
# machine is going to compile and link as if it were
|
||||||
|
# MACOSX_DEPLOYMENT_TARGET.
|
||||||
|
|
||||||
|
macver = _config_vars.get('MACOSX_DEPLOYMENT_TARGET', '')
|
||||||
|
macrelease = _get_system_version() or macver
|
||||||
|
macver = macver or macrelease
|
||||||
|
|
||||||
|
if macver:
|
||||||
|
release = macver
|
||||||
|
osname = "macosx"
|
||||||
|
|
||||||
|
# Use the original CFLAGS value, if available, so that we
|
||||||
|
# return the same machine type for the platform string.
|
||||||
|
# Otherwise, distutils may consider this a cross-compiling
|
||||||
|
# case and disallow installs.
|
||||||
|
cflags = _config_vars.get(_INITPRE+'CFLAGS',
|
||||||
|
_config_vars.get('CFLAGS', ''))
|
||||||
|
if ((macrelease + '.') >= '10.4.' and
|
||||||
|
'-arch' in cflags.strip()):
|
||||||
|
# The universal build will build fat binaries, but not on
|
||||||
|
# systems before 10.4
|
||||||
|
|
||||||
|
machine = 'fat'
|
||||||
|
|
||||||
|
archs = re.findall('-arch\s+(\S+)', cflags)
|
||||||
|
archs = tuple(sorted(set(archs)))
|
||||||
|
|
||||||
|
if len(archs) == 1:
|
||||||
|
machine = archs[0]
|
||||||
|
elif archs == ('i386', 'ppc'):
|
||||||
|
machine = 'fat'
|
||||||
|
elif archs == ('i386', 'x86_64'):
|
||||||
|
machine = 'intel'
|
||||||
|
elif archs == ('i386', 'ppc', 'x86_64'):
|
||||||
|
machine = 'fat3'
|
||||||
|
elif archs == ('ppc64', 'x86_64'):
|
||||||
|
machine = 'fat64'
|
||||||
|
elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
|
||||||
|
machine = 'universal'
|
||||||
|
else:
|
||||||
|
raise ValueError(
|
||||||
|
"Don't know machine value for archs=%r" % (archs,))
|
||||||
|
|
||||||
|
elif machine == 'i386':
|
||||||
|
# On OSX the machine type returned by uname is always the
|
||||||
|
# 32-bit variant, even if the executable architecture is
|
||||||
|
# the 64-bit variant
|
||||||
|
if sys.maxsize >= 2**32:
|
||||||
|
machine = 'x86_64'
|
||||||
|
|
||||||
|
elif machine in ('PowerPC', 'Power_Macintosh'):
|
||||||
|
# Pick a sane name for the PPC architecture.
|
||||||
|
# See 'i386' case
|
||||||
|
if sys.maxsize >= 2**32:
|
||||||
|
machine = 'ppc64'
|
||||||
|
else:
|
||||||
|
machine = 'ppc'
|
||||||
|
|
||||||
|
return (osname, release, machine)
|
|
@ -172,6 +172,21 @@ def customize_compiler(compiler):
|
||||||
varies across Unices and is stored in Python's Makefile.
|
varies across Unices and is stored in Python's Makefile.
|
||||||
"""
|
"""
|
||||||
if compiler.compiler_type == "unix":
|
if compiler.compiler_type == "unix":
|
||||||
|
if sys.platform == "darwin":
|
||||||
|
# Perform first-time customization of compiler-related
|
||||||
|
# config vars on OS X now that we know we need a compiler.
|
||||||
|
# This is primarily to support Pythons from binary
|
||||||
|
# installers. The kind and paths to build tools on
|
||||||
|
# the user system may vary significantly from the system
|
||||||
|
# that Python itself was built on. Also the user OS
|
||||||
|
# version and build tools may not support the same set
|
||||||
|
# of CPU architectures for universal builds.
|
||||||
|
global _config_vars
|
||||||
|
if not _config_vars.get('CUSTOMIZED_OSX_COMPILER', ''):
|
||||||
|
import _osx_support
|
||||||
|
_osx_support.customize_compiler(_config_vars)
|
||||||
|
_config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
|
||||||
|
|
||||||
(cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
|
(cc, cxx, opt, cflags, ccshared, ldshared, so_ext, ar, ar_flags) = \
|
||||||
get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
|
get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS',
|
||||||
'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
|
'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS')
|
||||||
|
@ -494,35 +509,12 @@ def _init_os2():
|
||||||
_config_vars = g
|
_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):
|
def get_config_vars(*args):
|
||||||
"""With no arguments, return a dictionary of all configuration
|
"""With no arguments, return a dictionary of all configuration
|
||||||
variables relevant for the current platform. Generally this includes
|
variables relevant for the current platform. Generally this includes
|
||||||
everything needed to build extensions and install both pure modules and
|
everything needed to build extensions and install both pure modules and
|
||||||
extensions. On Unix, this means every variable defined in Python's
|
extensions. On Unix, this means every variable defined in Python's
|
||||||
installed Makefile; on Windows and Mac OS it's a much smaller set.
|
installed Makefile; on Windows it's a much smaller set.
|
||||||
|
|
||||||
With arguments, return a list of values that result from looking up
|
With arguments, return a list of values that result from looking up
|
||||||
each argument in the configuration variable dictionary.
|
each argument in the configuration variable dictionary.
|
||||||
|
@ -555,153 +547,11 @@ def get_config_vars(*args):
|
||||||
srcdir = os.path.join(base, _config_vars['srcdir'])
|
srcdir = os.path.join(base, _config_vars['srcdir'])
|
||||||
_config_vars['srcdir'] = os.path.normpath(srcdir)
|
_config_vars['srcdir'] = os.path.normpath(srcdir)
|
||||||
|
|
||||||
|
# OS X platforms require special customization to handle
|
||||||
|
# multi-architecture, multi-os-version installers
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
from distutils.spawn import find_executable
|
import _osx_support
|
||||||
|
_osx_support.customize_config_vars(_config_vars)
|
||||||
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.
|
|
||||||
# This is needed when building extensions on a 10.3 system
|
|
||||||
# using a universal build of python.
|
|
||||||
for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
flags = _config_vars[key]
|
|
||||||
flags = re.sub('-arch\s+\w+\s', ' ', flags, re.ASCII)
|
|
||||||
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
|
|
||||||
_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', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
|
|
||||||
flags = _config_vars[key]
|
|
||||||
flags = re.sub('-arch\s+\w+\s', ' ', flags)
|
|
||||||
flags = flags + ' ' + arch
|
|
||||||
_config_vars[key] = flags
|
|
||||||
|
|
||||||
# If we're on OSX 10.5 or later and the user tries to
|
|
||||||
# compiles an extension using an SDK that is not present
|
|
||||||
# on the current machine it is better to not use an SDK
|
|
||||||
# than to fail.
|
|
||||||
#
|
|
||||||
# The major usecase for this is users using a Python.org
|
|
||||||
# binary installer on OSX 10.6: that installer uses
|
|
||||||
# the 10.4u SDK, but that SDK is not installed by default
|
|
||||||
# when you install Xcode.
|
|
||||||
#
|
|
||||||
m = re.search('-isysroot\s+(\S+)', _config_vars['CFLAGS'])
|
|
||||||
if m is not None:
|
|
||||||
sdk = m.group(1)
|
|
||||||
if not os.path.exists(sdk):
|
|
||||||
for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
|
|
||||||
flags = _config_vars[key]
|
|
||||||
flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
|
|
||||||
_config_vars[key] = flags
|
|
||||||
|
|
||||||
if args:
|
if args:
|
||||||
vals = []
|
vals = []
|
||||||
|
|
|
@ -13,6 +13,7 @@ from distutils import util # used to patch _environ_checked
|
||||||
from distutils.sysconfig import get_config_vars
|
from distutils.sysconfig import get_config_vars
|
||||||
from distutils import sysconfig
|
from distutils import sysconfig
|
||||||
from distutils.tests import support
|
from distutils.tests import support
|
||||||
|
import _osx_support
|
||||||
|
|
||||||
class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
|
|
||||||
|
@ -92,6 +93,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
('Darwin Kernel Version 8.11.1: '
|
('Darwin Kernel Version 8.11.1: '
|
||||||
'Wed Oct 10 18:23:28 PDT 2007; '
|
'Wed Oct 10 18:23:28 PDT 2007; '
|
||||||
'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
|
'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
||||||
|
|
||||||
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
||||||
|
@ -105,6 +107,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
sys.maxsize = cursize
|
sys.maxsize = cursize
|
||||||
|
|
||||||
# macbook with fat binaries (fat, universal or fat64)
|
# macbook with fat binaries (fat, universal or fat64)
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
|
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
|
||||||
get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
|
@ -113,10 +116,12 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
|
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1'
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
||||||
|
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
@ -124,18 +129,21 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-intel')
|
self.assertEqual(get_platform(), 'macosx-10.4-intel')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
'-dynamic -DNDEBUG -g -O3')
|
'-dynamic -DNDEBUG -g -O3')
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat3')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat3')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
'-dynamic -DNDEBUG -g -O3')
|
'-dynamic -DNDEBUG -g -O3')
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-universal')
|
self.assertEqual(get_platform(), 'macosx-10.4-universal')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
@ -144,6 +152,7 @@ class UtilTestCase(support.EnvironGuard, unittest.TestCase):
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
|
||||||
|
|
||||||
for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
|
for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
|
|
@ -23,6 +23,9 @@ from distutils.errors import \
|
||||||
DistutilsExecError, CompileError, LibError, LinkError
|
DistutilsExecError, CompileError, LibError, LinkError
|
||||||
from distutils import log
|
from distutils import log
|
||||||
|
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
import _osx_support
|
||||||
|
|
||||||
# XXX Things not currently handled:
|
# XXX Things not currently handled:
|
||||||
# * optimization/debug/warning flags; we just use whatever's in Python's
|
# * optimization/debug/warning flags; we just use whatever's in Python's
|
||||||
# Makefile and live with it. Is this adequate? If not, we might
|
# Makefile and live with it. Is this adequate? If not, we might
|
||||||
|
@ -38,68 +41,6 @@ from distutils import log
|
||||||
# should just happily stuff them into the preprocessor/compiler/linker
|
# should just happily stuff them into the preprocessor/compiler/linker
|
||||||
# options and carry on.
|
# options and carry on.
|
||||||
|
|
||||||
def _darwin_compiler_fixup(compiler_so, cc_args):
|
|
||||||
"""
|
|
||||||
This function will strip '-isysroot PATH' and '-arch ARCH' from the
|
|
||||||
compile flags if the user has specified one them in extra_compile_flags.
|
|
||||||
|
|
||||||
This is needed because '-arch ARCH' adds another architecture to the
|
|
||||||
build, without a way to remove an architecture. Furthermore GCC will
|
|
||||||
barf if multiple '-isysroot' arguments are present.
|
|
||||||
"""
|
|
||||||
stripArch = stripSysroot = False
|
|
||||||
|
|
||||||
compiler_so = list(compiler_so)
|
|
||||||
kernel_version = os.uname()[2] # 8.4.3
|
|
||||||
major_version = int(kernel_version.split('.')[0])
|
|
||||||
|
|
||||||
if major_version < 8:
|
|
||||||
# OSX before 10.4.0, these don't support -arch and -isysroot at
|
|
||||||
# all.
|
|
||||||
stripArch = stripSysroot = True
|
|
||||||
else:
|
|
||||||
stripArch = '-arch' in cc_args
|
|
||||||
stripSysroot = '-isysroot' in cc_args
|
|
||||||
|
|
||||||
if stripArch or 'ARCHFLAGS' in os.environ:
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
index = compiler_so.index('-arch')
|
|
||||||
# Strip this argument and the next one:
|
|
||||||
del compiler_so[index:index+2]
|
|
||||||
except ValueError:
|
|
||||||
break
|
|
||||||
|
|
||||||
if 'ARCHFLAGS' in os.environ and not stripArch:
|
|
||||||
# User specified different -arch flags in the environ,
|
|
||||||
# see also distutils.sysconfig
|
|
||||||
compiler_so = compiler_so + os.environ['ARCHFLAGS'].split()
|
|
||||||
|
|
||||||
if stripSysroot:
|
|
||||||
try:
|
|
||||||
index = compiler_so.index('-isysroot')
|
|
||||||
# Strip this argument and the next one:
|
|
||||||
del compiler_so[index:index+2]
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Check if the SDK that is used during compilation actually exists,
|
|
||||||
# the universal build requires the usage of a universal SDK and not all
|
|
||||||
# users have that installed by default.
|
|
||||||
sysroot = None
|
|
||||||
if '-isysroot' in cc_args:
|
|
||||||
idx = cc_args.index('-isysroot')
|
|
||||||
sysroot = cc_args[idx+1]
|
|
||||||
elif '-isysroot' in compiler_so:
|
|
||||||
idx = compiler_so.index('-isysroot')
|
|
||||||
sysroot = compiler_so[idx+1]
|
|
||||||
|
|
||||||
if sysroot and not os.path.isdir(sysroot):
|
|
||||||
log.warn("Compiling with an SDK that doesn't seem to exist: %s",
|
|
||||||
sysroot)
|
|
||||||
log.warn("Please check your Xcode installation")
|
|
||||||
|
|
||||||
return compiler_so
|
|
||||||
|
|
||||||
class UnixCCompiler(CCompiler):
|
class UnixCCompiler(CCompiler):
|
||||||
|
|
||||||
|
@ -168,7 +109,8 @@ class UnixCCompiler(CCompiler):
|
||||||
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
||||||
compiler_so = self.compiler_so
|
compiler_so = self.compiler_so
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
compiler_so = _darwin_compiler_fixup(compiler_so, cc_args + extra_postargs)
|
compiler_so = _osx_support.compiler_fixup(compiler_so,
|
||||||
|
cc_args + extra_postargs)
|
||||||
try:
|
try:
|
||||||
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
|
self.spawn(compiler_so + cc_args + [src, '-o', obj] +
|
||||||
extra_postargs)
|
extra_postargs)
|
||||||
|
@ -247,7 +189,7 @@ class UnixCCompiler(CCompiler):
|
||||||
linker[i] = self.compiler_cxx[i]
|
linker[i] = self.compiler_cxx[i]
|
||||||
|
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
linker = _darwin_compiler_fixup(linker, ld_args)
|
linker = _osx_support.compiler_fixup(linker, ld_args)
|
||||||
|
|
||||||
self.spawn(linker + ld_args)
|
self.spawn(linker + ld_args)
|
||||||
except DistutilsExecError as msg:
|
except DistutilsExecError as msg:
|
||||||
|
|
|
@ -98,94 +98,10 @@ def get_platform ():
|
||||||
if m:
|
if m:
|
||||||
release = m.group()
|
release = m.group()
|
||||||
elif osname[:6] == "darwin":
|
elif osname[:6] == "darwin":
|
||||||
#
|
import _osx_support, distutils.sysconfig
|
||||||
# For our purposes, we'll assume that the system version from
|
osname, release, machine = _osx_support.get_platform_osx(
|
||||||
# distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
|
distutils.sysconfig.get_config_vars(),
|
||||||
# to. This makes the compatibility story a bit more sane because the
|
osname, release, machine)
|
||||||
# machine is going to compile and link as if it were
|
|
||||||
# MACOSX_DEPLOYMENT_TARGET.
|
|
||||||
from distutils.sysconfig import get_config_vars
|
|
||||||
cfgvars = get_config_vars()
|
|
||||||
|
|
||||||
macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
|
|
||||||
|
|
||||||
if 1:
|
|
||||||
# Always calculate the release of the running machine,
|
|
||||||
# needed to determine if we can build fat binaries or not.
|
|
||||||
|
|
||||||
macrelease = macver
|
|
||||||
# Get the system version. Reading this plist is a documented
|
|
||||||
# way to get the system version (see the documentation for
|
|
||||||
# the Gestalt Manager)
|
|
||||||
try:
|
|
||||||
f = open('/System/Library/CoreServices/SystemVersion.plist')
|
|
||||||
except IOError:
|
|
||||||
# We're on a plain darwin box, fall back to the default
|
|
||||||
# behaviour.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
m = re.search(
|
|
||||||
r'<key>ProductUserVisibleVersion</key>\s*' +
|
|
||||||
r'<string>(.*?)</string>', f.read())
|
|
||||||
if m is not None:
|
|
||||||
macrelease = '.'.join(m.group(1).split('.')[:2])
|
|
||||||
# else: fall back to the default behaviour
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
if not macver:
|
|
||||||
macver = macrelease
|
|
||||||
|
|
||||||
if macver:
|
|
||||||
from distutils.sysconfig import get_config_vars
|
|
||||||
release = macver
|
|
||||||
osname = "macosx"
|
|
||||||
|
|
||||||
if (macrelease + '.') >= '10.4.' and \
|
|
||||||
'-arch' in get_config_vars().get('CFLAGS', '').strip():
|
|
||||||
# The universal build will build fat binaries, but not on
|
|
||||||
# systems before 10.4
|
|
||||||
#
|
|
||||||
# Try to detect 4-way universal builds, those have machine-type
|
|
||||||
# 'universal' instead of 'fat'.
|
|
||||||
|
|
||||||
machine = 'fat'
|
|
||||||
cflags = get_config_vars().get('CFLAGS')
|
|
||||||
|
|
||||||
archs = re.findall('-arch\s+(\S+)', cflags)
|
|
||||||
archs = tuple(sorted(set(archs)))
|
|
||||||
|
|
||||||
if len(archs) == 1:
|
|
||||||
machine = archs[0]
|
|
||||||
elif archs == ('i386', 'ppc'):
|
|
||||||
machine = 'fat'
|
|
||||||
elif archs == ('i386', 'x86_64'):
|
|
||||||
machine = 'intel'
|
|
||||||
elif archs == ('i386', 'ppc', 'x86_64'):
|
|
||||||
machine = 'fat3'
|
|
||||||
elif archs == ('ppc64', 'x86_64'):
|
|
||||||
machine = 'fat64'
|
|
||||||
elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
|
|
||||||
machine = 'universal'
|
|
||||||
else:
|
|
||||||
raise ValueError(
|
|
||||||
"Don't know machine value for archs=%r"%(archs,))
|
|
||||||
|
|
||||||
elif machine == 'i386':
|
|
||||||
# On OSX the machine type returned by uname is always the
|
|
||||||
# 32-bit variant, even if the executable architecture is
|
|
||||||
# the 64-bit variant
|
|
||||||
if sys.maxsize >= 2**32:
|
|
||||||
machine = 'x86_64'
|
|
||||||
|
|
||||||
elif machine in ('PowerPC', 'Power_Macintosh'):
|
|
||||||
# Pick a sane name for the PPC architecture.
|
|
||||||
machine = 'ppc'
|
|
||||||
|
|
||||||
# See 'i386' case
|
|
||||||
if sys.maxsize >= 2**32:
|
|
||||||
machine = 'ppc64'
|
|
||||||
|
|
||||||
return "%s-%s-%s" % (osname, release, machine)
|
return "%s-%s-%s" % (osname, release, machine)
|
||||||
|
|
||||||
|
|
154
Lib/sysconfig.py
154
Lib/sysconfig.py
|
@ -497,7 +497,7 @@ def get_config_vars(*args):
|
||||||
variables relevant for the current platform.
|
variables relevant for the current platform.
|
||||||
|
|
||||||
On Unix, this means every variable defined in Python's installed Makefile;
|
On Unix, this means every variable defined in Python's installed Makefile;
|
||||||
On Windows and Mac OS it's a much smaller set.
|
On Windows it's a much smaller set.
|
||||||
|
|
||||||
With arguments, return a list of values that result from looking up
|
With arguments, return a list of values that result from looking up
|
||||||
each argument in the configuration variable dictionary.
|
each argument in the configuration variable dictionary.
|
||||||
|
@ -556,64 +556,11 @@ def get_config_vars(*args):
|
||||||
srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
|
srcdir = os.path.join(base, _CONFIG_VARS['srcdir'])
|
||||||
_CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
|
_CONFIG_VARS['srcdir'] = os.path.normpath(srcdir)
|
||||||
|
|
||||||
|
# OS X platforms require special customization to handle
|
||||||
|
# multi-architecture, multi-os-version installers
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
kernel_version = os.uname().release # Kernel version (8.4.3)
|
import _osx_support
|
||||||
major_version = int(kernel_version.split('.')[0])
|
_osx_support.customize_config_vars(_CONFIG_VARS)
|
||||||
|
|
||||||
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.
|
|
||||||
# This is needed when building extensions on a 10.3 system
|
|
||||||
# using a universal build of python.
|
|
||||||
for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
flags = _CONFIG_VARS[key]
|
|
||||||
flags = re.sub('-arch\s+\w+\s', ' ', flags)
|
|
||||||
flags = re.sub('-isysroot [^ \t]*', ' ', flags)
|
|
||||||
_CONFIG_VARS[key] = flags
|
|
||||||
else:
|
|
||||||
# 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', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
|
|
||||||
flags = _CONFIG_VARS[key]
|
|
||||||
flags = re.sub('-arch\s+\w+\s', ' ', flags)
|
|
||||||
flags = flags + ' ' + arch
|
|
||||||
_CONFIG_VARS[key] = flags
|
|
||||||
|
|
||||||
# If we're on OSX 10.5 or later and the user tries to
|
|
||||||
# compiles an extension using an SDK that is not present
|
|
||||||
# on the current machine it is better to not use an SDK
|
|
||||||
# than to fail.
|
|
||||||
#
|
|
||||||
# The major usecase for this is users using a Python.org
|
|
||||||
# binary installer on OSX 10.6: that installer uses
|
|
||||||
# the 10.4u SDK, but that SDK is not installed by default
|
|
||||||
# when you install Xcode.
|
|
||||||
#
|
|
||||||
CFLAGS = _CONFIG_VARS.get('CFLAGS', '')
|
|
||||||
m = re.search('-isysroot\s+(\S+)', CFLAGS)
|
|
||||||
if m is not None:
|
|
||||||
sdk = m.group(1)
|
|
||||||
if not os.path.exists(sdk):
|
|
||||||
for key in ('LDFLAGS', 'BASECFLAGS', 'LDSHARED',
|
|
||||||
# a number of derived variables. These need to be
|
|
||||||
# patched up as well.
|
|
||||||
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
|
|
||||||
|
|
||||||
flags = _CONFIG_VARS[key]
|
|
||||||
flags = re.sub('-isysroot\s+\S+(\s|$)', ' ', flags)
|
|
||||||
_CONFIG_VARS[key] = flags
|
|
||||||
|
|
||||||
if args:
|
if args:
|
||||||
vals = []
|
vals = []
|
||||||
|
@ -673,8 +620,7 @@ def get_platform():
|
||||||
return sys.platform
|
return sys.platform
|
||||||
|
|
||||||
if os.name != "posix" or not hasattr(os, 'uname'):
|
if os.name != "posix" or not hasattr(os, 'uname'):
|
||||||
# XXX what about the architecture? NT is Intel or Alpha,
|
# XXX what about the architecture? NT is Intel or Alpha
|
||||||
# Mac OS is M68k or PPC, etc.
|
|
||||||
return sys.platform
|
return sys.platform
|
||||||
|
|
||||||
# Set for cross builds explicitly
|
# Set for cross builds explicitly
|
||||||
|
@ -716,90 +662,10 @@ def get_platform():
|
||||||
if m:
|
if m:
|
||||||
release = m.group()
|
release = m.group()
|
||||||
elif osname[:6] == "darwin":
|
elif osname[:6] == "darwin":
|
||||||
#
|
import _osx_support
|
||||||
# For our purposes, we'll assume that the system version from
|
osname, release, machine = _osx_support.get_platform_osx(
|
||||||
# distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set
|
get_config_vars(),
|
||||||
# to. This makes the compatibility story a bit more sane because the
|
osname, release, machine)
|
||||||
# machine is going to compile and link as if it were
|
|
||||||
# MACOSX_DEPLOYMENT_TARGET.
|
|
||||||
cfgvars = get_config_vars()
|
|
||||||
macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET')
|
|
||||||
|
|
||||||
if True:
|
|
||||||
# Always calculate the release of the running machine,
|
|
||||||
# needed to determine if we can build fat binaries or not.
|
|
||||||
|
|
||||||
macrelease = macver
|
|
||||||
# Get the system version. Reading this plist is a documented
|
|
||||||
# way to get the system version (see the documentation for
|
|
||||||
# the Gestalt Manager)
|
|
||||||
try:
|
|
||||||
f = open('/System/Library/CoreServices/SystemVersion.plist')
|
|
||||||
except IOError:
|
|
||||||
# We're on a plain darwin box, fall back to the default
|
|
||||||
# behaviour.
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
m = re.search(r'<key>ProductUserVisibleVersion</key>\s*'
|
|
||||||
r'<string>(.*?)</string>', f.read())
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
if m is not None:
|
|
||||||
macrelease = '.'.join(m.group(1).split('.')[:2])
|
|
||||||
# else: fall back to the default behaviour
|
|
||||||
|
|
||||||
if not macver:
|
|
||||||
macver = macrelease
|
|
||||||
|
|
||||||
if macver:
|
|
||||||
release = macver
|
|
||||||
osname = "macosx"
|
|
||||||
|
|
||||||
if ((macrelease + '.') >= '10.4.' and
|
|
||||||
'-arch' in get_config_vars().get('CFLAGS', '').strip()):
|
|
||||||
# The universal build will build fat binaries, but not on
|
|
||||||
# systems before 10.4
|
|
||||||
#
|
|
||||||
# Try to detect 4-way universal builds, those have machine-type
|
|
||||||
# 'universal' instead of 'fat'.
|
|
||||||
|
|
||||||
machine = 'fat'
|
|
||||||
cflags = get_config_vars().get('CFLAGS')
|
|
||||||
|
|
||||||
archs = re.findall('-arch\s+(\S+)', cflags)
|
|
||||||
archs = tuple(sorted(set(archs)))
|
|
||||||
|
|
||||||
if len(archs) == 1:
|
|
||||||
machine = archs[0]
|
|
||||||
elif archs == ('i386', 'ppc'):
|
|
||||||
machine = 'fat'
|
|
||||||
elif archs == ('i386', 'x86_64'):
|
|
||||||
machine = 'intel'
|
|
||||||
elif archs == ('i386', 'ppc', 'x86_64'):
|
|
||||||
machine = 'fat3'
|
|
||||||
elif archs == ('ppc64', 'x86_64'):
|
|
||||||
machine = 'fat64'
|
|
||||||
elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'):
|
|
||||||
machine = 'universal'
|
|
||||||
else:
|
|
||||||
raise ValueError(
|
|
||||||
"Don't know machine value for archs=%r" % (archs,))
|
|
||||||
|
|
||||||
elif machine == 'i386':
|
|
||||||
# On OSX the machine type returned by uname is always the
|
|
||||||
# 32-bit variant, even if the executable architecture is
|
|
||||||
# the 64-bit variant
|
|
||||||
if sys.maxsize >= 2**32:
|
|
||||||
machine = 'x86_64'
|
|
||||||
|
|
||||||
elif machine in ('PowerPC', 'Power_Macintosh'):
|
|
||||||
# Pick a sane name for the PPC architecture.
|
|
||||||
# See 'i386' case
|
|
||||||
if sys.maxsize >= 2**32:
|
|
||||||
machine = 'ppc64'
|
|
||||||
else:
|
|
||||||
machine = 'ppc'
|
|
||||||
|
|
||||||
return "%s-%s-%s" % (osname, release, machine)
|
return "%s-%s-%s" % (osname, release, machine)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
"""
|
||||||
|
Test suite for _osx_support: shared OS X support functions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import shutil
|
||||||
|
import stat
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import test.support
|
||||||
|
|
||||||
|
import _osx_support
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform.startswith("darwin"), "requires OS X")
|
||||||
|
class Test_OSXSupport(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
self.prog_name = 'bogus_program_xxxx'
|
||||||
|
self.temp_path_dir = os.path.abspath(os.getcwd())
|
||||||
|
|
||||||
|
def add_expected_saved_initial_values(self, config_vars, expected_vars):
|
||||||
|
# Ensure that the initial values for all modified config vars
|
||||||
|
# are also saved with modified keys.
|
||||||
|
expected_vars.update(('_OSX_SUPPORT_INITIAL_'+ k,
|
||||||
|
config_vars[k]) for k in config_vars
|
||||||
|
if config_vars[k] != expected_vars[k])
|
||||||
|
|
||||||
|
def test__find_executable(self):
|
||||||
|
with test.support.EnvironmentVarGuard() as env:
|
||||||
|
if env['PATH']:
|
||||||
|
env['PATH'] = env['PATH'] + ':'
|
||||||
|
env['PATH'] = env['PATH'] + os.path.abspath(self.temp_path_dir)
|
||||||
|
test.support.unlink(self.prog_name)
|
||||||
|
self.assertIsNone(_osx_support._find_executable(self.prog_name))
|
||||||
|
self.addCleanup(test.support.unlink, self.prog_name)
|
||||||
|
with open(self.prog_name, 'w') as f:
|
||||||
|
f.write("#!/bin/sh\n/bin/echo OK\n")
|
||||||
|
os.chmod(self.prog_name, stat.S_IRWXU)
|
||||||
|
self.assertEqual(self.prog_name,
|
||||||
|
_osx_support._find_executable(self.prog_name))
|
||||||
|
|
||||||
|
def test__read_output(self):
|
||||||
|
with test.support.EnvironmentVarGuard() as env:
|
||||||
|
if env['PATH']:
|
||||||
|
env['PATH'] = env['PATH'] + ':'
|
||||||
|
env['PATH'] = env['PATH'] + os.path.abspath(self.temp_path_dir)
|
||||||
|
test.support.unlink(self.prog_name)
|
||||||
|
self.addCleanup(test.support.unlink, self.prog_name)
|
||||||
|
with open(self.prog_name, 'w') as f:
|
||||||
|
f.write("#!/bin/sh\n/bin/echo ExpectedOutput\n")
|
||||||
|
os.chmod(self.prog_name, stat.S_IRWXU)
|
||||||
|
self.assertEqual('ExpectedOutput',
|
||||||
|
_osx_support._read_output(self.prog_name))
|
||||||
|
|
||||||
|
def test__find_build_tool(self):
|
||||||
|
out = _osx_support._find_build_tool('cc')
|
||||||
|
self.assertTrue(os.path.isfile(out),
|
||||||
|
'cc not found - check xcode-select')
|
||||||
|
|
||||||
|
def test__get_system_version(self):
|
||||||
|
self.assertTrue(platform.mac_ver()[0].startswith(
|
||||||
|
_osx_support._get_system_version()))
|
||||||
|
|
||||||
|
def test__remove_original_values(self):
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'gcc-test -pthreads',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang -pthreads',
|
||||||
|
}
|
||||||
|
cv = 'CC'
|
||||||
|
newvalue = 'clang -pthreads'
|
||||||
|
_osx_support._save_modified_value(config_vars, cv, newvalue)
|
||||||
|
self.assertNotEqual(expected_vars, config_vars)
|
||||||
|
_osx_support._remove_original_values(config_vars)
|
||||||
|
self.assertEqual(expected_vars, config_vars)
|
||||||
|
|
||||||
|
def test__save_modified_value(self):
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'gcc-test -pthreads',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang -pthreads',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
cv = 'CC'
|
||||||
|
newvalue = 'clang -pthreads'
|
||||||
|
_osx_support._save_modified_value(config_vars, cv, newvalue)
|
||||||
|
self.assertEqual(expected_vars, config_vars)
|
||||||
|
|
||||||
|
def test__save_modified_value_unchanged(self):
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'gcc-test -pthreads',
|
||||||
|
}
|
||||||
|
expected_vars = config_vars.copy()
|
||||||
|
cv = 'CC'
|
||||||
|
newvalue = 'gcc-test -pthreads'
|
||||||
|
_osx_support._save_modified_value(config_vars, cv, newvalue)
|
||||||
|
self.assertEqual(expected_vars, config_vars)
|
||||||
|
|
||||||
|
def test__supports_universal_builds(self):
|
||||||
|
import platform
|
||||||
|
self.assertEqual(platform.mac_ver()[0].split('.') >= ['10', '4'],
|
||||||
|
_osx_support._supports_universal_builds())
|
||||||
|
|
||||||
|
def test__find_appropriate_compiler(self):
|
||||||
|
compilers = (
|
||||||
|
('gcc-test', 'i686-apple-darwin11-llvm-gcc-4.2'),
|
||||||
|
('clang', 'clang version 3.1'),
|
||||||
|
)
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'gcc-test -pthreads',
|
||||||
|
'CXX': 'cc++-test',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-test -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-test -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang -pthreads',
|
||||||
|
'CXX': 'clang++',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'clang -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'clang -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
|
||||||
|
with test.support.EnvironmentVarGuard() as env:
|
||||||
|
suffix = (':' + env['PATH']) if env['PATH'] else ''
|
||||||
|
env['PATH'] = os.path.abspath(self.temp_path_dir) + suffix
|
||||||
|
for c_name, c_output in compilers:
|
||||||
|
test.support.unlink(c_name)
|
||||||
|
self.addCleanup(test.support.unlink, c_name)
|
||||||
|
with open(c_name, 'w') as f:
|
||||||
|
f.write("#!/bin/sh\n/bin/echo " + c_output)
|
||||||
|
os.chmod(c_name, stat.S_IRWXU)
|
||||||
|
self.assertEqual(expected_vars,
|
||||||
|
_osx_support._find_appropriate_compiler(
|
||||||
|
config_vars))
|
||||||
|
|
||||||
|
def test__remove_universal_flags(self):
|
||||||
|
config_vars = {
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 ',
|
||||||
|
'LDFLAGS': ' -g',
|
||||||
|
'CPPFLAGS': '-I. ',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -g',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
|
||||||
|
self.assertEqual(expected_vars,
|
||||||
|
_osx_support._remove_universal_flags(
|
||||||
|
config_vars))
|
||||||
|
|
||||||
|
@unittest.skipUnless(shutil.which('clang'),'test requires clang')
|
||||||
|
def test__remove_unsupported_archs(self):
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch i386 ',
|
||||||
|
'LDFLAGS': ' -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
|
||||||
|
self.assertEqual(expected_vars,
|
||||||
|
_osx_support._remove_unsupported_archs(
|
||||||
|
config_vars))
|
||||||
|
|
||||||
|
def test__override_all_archs(self):
|
||||||
|
with test.support.EnvironmentVarGuard() as env:
|
||||||
|
env['ARCHFLAGS'] = '-arch x86_64'
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.4u.sdk -g',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch x86_64',
|
||||||
|
'LDFLAGS': ' -g -arch x86_64',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.4u.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -g -arch x86_64',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -isysroot '
|
||||||
|
'/Developer/SDKs/MacOSX10.4u.sdk -g -arch x86_64',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
|
||||||
|
self.assertEqual(expected_vars,
|
||||||
|
_osx_support._override_all_archs(
|
||||||
|
config_vars))
|
||||||
|
|
||||||
|
def test__check_for_unavailable_sdk(self):
|
||||||
|
config_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.1.sdk',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. -isysroot /Developer/SDKs/MacOSX10.1.sdk',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.1.sdk -g',
|
||||||
|
}
|
||||||
|
expected_vars = {
|
||||||
|
'CC': 'clang',
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 '
|
||||||
|
' ',
|
||||||
|
'LDFLAGS': '-arch ppc -arch i386 -g',
|
||||||
|
'CPPFLAGS': '-I. ',
|
||||||
|
'BLDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 -g',
|
||||||
|
'LDSHARED': 'gcc-4.0 -bundle -arch ppc -arch i386 '
|
||||||
|
' -g',
|
||||||
|
}
|
||||||
|
self.add_expected_saved_initial_values(config_vars, expected_vars)
|
||||||
|
|
||||||
|
self.assertEqual(expected_vars,
|
||||||
|
_osx_support._check_for_unavailable_sdk(
|
||||||
|
config_vars))
|
||||||
|
|
||||||
|
def test_get_platform_osx(self):
|
||||||
|
# Note, get_platform_osx is currently tested more extensively
|
||||||
|
# indirectly by test_sysconfig and test_distutils
|
||||||
|
config_vars = {
|
||||||
|
'CFLAGS': '-fno-strict-aliasing -g -O3 -arch ppc -arch i386 '
|
||||||
|
'-isysroot /Developer/SDKs/MacOSX10.1.sdk',
|
||||||
|
'MACOSX_DEPLOYMENT_TARGET': '10.6',
|
||||||
|
}
|
||||||
|
result = _osx_support.get_platform_osx(config_vars, ' ', ' ', ' ')
|
||||||
|
self.assertEqual(('macosx', '10.6', 'fat'), result)
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
test.support.run_unittest(Test_OSXSupport)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_main()
|
|
@ -13,6 +13,7 @@ from sysconfig import (get_paths, get_platform, get_config_vars,
|
||||||
get_path, get_path_names, _INSTALL_SCHEMES,
|
get_path, get_path_names, _INSTALL_SCHEMES,
|
||||||
_get_default_scheme, _expand_vars,
|
_get_default_scheme, _expand_vars,
|
||||||
get_scheme_names, get_config_var, _main)
|
get_scheme_names, get_config_var, _main)
|
||||||
|
import _osx_support
|
||||||
|
|
||||||
class TestSysConfig(unittest.TestCase):
|
class TestSysConfig(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -134,6 +135,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
('Darwin Kernel Version 8.11.1: '
|
('Darwin Kernel Version 8.11.1: '
|
||||||
'Wed Oct 10 18:23:28 PDT 2007; '
|
'Wed Oct 10 18:23:28 PDT 2007; '
|
||||||
'root:xnu-792.25.20~1/RELEASE_I386'), 'PowerPC'))
|
'root:xnu-792.25.20~1/RELEASE_I386'), 'PowerPC'))
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
||||||
|
|
||||||
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
||||||
|
@ -152,7 +154,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
('Darwin Kernel Version 8.11.1: '
|
('Darwin Kernel Version 8.11.1: '
|
||||||
'Wed Oct 10 18:23:28 PDT 2007; '
|
'Wed Oct 10 18:23:28 PDT 2007; '
|
||||||
'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
|
'root:xnu-792.25.20~1/RELEASE_I386'), 'i386'))
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
|
||||||
|
|
||||||
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
get_config_vars()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g '
|
||||||
|
@ -167,6 +169,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
sys.maxsize = maxint
|
sys.maxsize = maxint
|
||||||
|
|
||||||
# macbook with fat binaries (fat, universal or fat64)
|
# macbook with fat binaries (fat, universal or fat64)
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
|
get_config_vars()['MACOSX_DEPLOYMENT_TARGET'] = '10.4'
|
||||||
get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
|
@ -175,6 +178,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
@ -182,18 +186,21 @@ class TestSysConfig(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-intel')
|
self.assertEqual(get_platform(), 'macosx-10.4-intel')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
'-dynamic -DNDEBUG -g -O3')
|
'-dynamic -DNDEBUG -g -O3')
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat3')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat3')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch ppc64 -arch x86_64 -arch ppc -arch i386 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
'-dynamic -DNDEBUG -g -O3')
|
'-dynamic -DNDEBUG -g -O3')
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-universal')
|
self.assertEqual(get_platform(), 'macosx-10.4-universal')
|
||||||
|
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch x86_64 -arch ppc64 -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
@ -202,6 +209,7 @@ class TestSysConfig(unittest.TestCase):
|
||||||
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
|
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
|
||||||
|
|
||||||
for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
|
for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
|
||||||
|
_osx_support._remove_original_values(get_config_vars())
|
||||||
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
|
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
|
||||||
'/Developer/SDKs/MacOSX10.4u.sdk '
|
'/Developer/SDKs/MacOSX10.4u.sdk '
|
||||||
'-fno-strict-aliasing -fno-common '
|
'-fno-strict-aliasing -fno-common '
|
||||||
|
|
|
@ -137,6 +137,11 @@ Library
|
||||||
- Issue 10924: Fixed mksalt() to use a RNG that is suitable for cryptographic
|
- Issue 10924: Fixed mksalt() to use a RNG that is suitable for cryptographic
|
||||||
purpose.
|
purpose.
|
||||||
|
|
||||||
|
- Issue #15184: Ensure consistent results of OS X configuration
|
||||||
|
tailoring for universal builds by factoring out common OS X-specific
|
||||||
|
customizations from sysconfig, distutils.sysconfig, distutils.util,
|
||||||
|
and distutils.unixccompiler into a new module _osx_support.
|
||||||
|
|
||||||
C API
|
C API
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue