mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	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
					
				
					 9 changed files with 818 additions and 467 deletions
				
			
		
							
								
								
									
										488
									
								
								Lib/_osx_support.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								Lib/_osx_support.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -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. | ||||
|     """ | ||||
|     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) = \ | ||||
|             get_config_vars('CC', 'CXX', 'OPT', 'CFLAGS', | ||||
|                             'CCSHARED', 'LDSHARED', 'SO', 'AR', 'ARFLAGS') | ||||
|  | @ -494,35 +509,12 @@ 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 | ||||
|     everything needed to build extensions and install both pure modules and | ||||
|     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 | ||||
|     each argument in the configuration variable dictionary. | ||||
|  | @ -555,153 +547,11 @@ def get_config_vars(*args): | |||
|                 srcdir = os.path.join(base, _config_vars['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': | ||||
|             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. | ||||
|                 # 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 | ||||
|             import _osx_support | ||||
|             _osx_support.customize_config_vars(_config_vars) | ||||
| 
 | ||||
|     if args: | ||||
|         vals = [] | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| from distutils.sysconfig import get_config_vars | ||||
| from distutils import sysconfig | ||||
| from distutils.tests import support | ||||
| import _osx_support | ||||
| 
 | ||||
| class UtilTestCase(support.EnvironGuard, unittest.TestCase): | ||||
| 
 | ||||
|  | @ -92,6 +93,7 @@ def test_get_platform(self): | |||
|                    ('Darwin Kernel Version 8.11.1: ' | ||||
|                     'Wed Oct 10 18:23:28 PDT 2007; ' | ||||
|                     '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()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g ' | ||||
|  | @ -105,6 +107,7 @@ def test_get_platform(self): | |||
|             sys.maxsize = cursize | ||||
| 
 | ||||
|         # 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()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|  | @ -113,10 +116,12 @@ def test_get_platform(self): | |||
| 
 | ||||
|         self.assertEqual(get_platform(), 'macosx-10.4-fat') | ||||
| 
 | ||||
|         _osx_support._remove_original_values(get_config_vars()) | ||||
|         os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.1' | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|  | @ -124,18 +129,21 @@ def test_get_platform(self): | |||
| 
 | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|                                        '-dynamic -DNDEBUG -g -O3') | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|                                        '-dynamic -DNDEBUG -g -O3') | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|  | @ -144,6 +152,7 @@ def test_get_platform(self): | |||
|         self.assertEqual(get_platform(), 'macosx-10.4-fat64') | ||||
| 
 | ||||
|         for arch in ('ppc', 'i386', 'x86_64', 'ppc64'): | ||||
|             _osx_support._remove_original_values(get_config_vars()) | ||||
|             get_config_vars()['CFLAGS'] = ('-arch %s -isysroot ' | ||||
|                                            '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                            '-fno-strict-aliasing -fno-common ' | ||||
|  |  | |||
|  | @ -23,6 +23,9 @@ | |||
|      DistutilsExecError, CompileError, LibError, LinkError | ||||
| from distutils import log | ||||
| 
 | ||||
| if sys.platform == 'darwin': | ||||
|     import _osx_support | ||||
| 
 | ||||
| # XXX Things not currently handled: | ||||
| #   * optimization/debug/warning flags; we just use whatever's in Python's | ||||
| #     Makefile and live with it.  Is this adequate?  If not, we might | ||||
|  | @ -38,68 +41,6 @@ | |||
| #     should just happily stuff them into the preprocessor/compiler/linker | ||||
| #     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): | ||||
| 
 | ||||
|  | @ -168,7 +109,8 @@ def preprocess(self, source, output_file=None, macros=None, | |||
|     def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): | ||||
|         compiler_so = self.compiler_so | ||||
|         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: | ||||
|             self.spawn(compiler_so + cc_args + [src, '-o', obj] + | ||||
|                        extra_postargs) | ||||
|  | @ -247,7 +189,7 @@ def link(self, target_desc, objects, | |||
|                     linker[i] = self.compiler_cxx[i] | ||||
| 
 | ||||
|                 if sys.platform == 'darwin': | ||||
|                     linker = _darwin_compiler_fixup(linker, ld_args) | ||||
|                     linker = _osx_support.compiler_fixup(linker, ld_args) | ||||
| 
 | ||||
|                 self.spawn(linker + ld_args) | ||||
|             except DistutilsExecError as msg: | ||||
|  |  | |||
|  | @ -98,94 +98,10 @@ def get_platform (): | |||
|         if m: | ||||
|             release = m.group() | ||||
|     elif osname[:6] == "darwin": | ||||
|         # | ||||
|         # 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. | ||||
|         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' | ||||
|         import _osx_support, distutils.sysconfig | ||||
|         osname, release, machine = _osx_support.get_platform_osx( | ||||
|                                         distutils.sysconfig.get_config_vars(), | ||||
|                                         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. | ||||
| 
 | ||||
|     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 | ||||
|     each argument in the configuration variable dictionary. | ||||
|  | @ -556,64 +556,11 @@ def get_config_vars(*args): | |||
|                 srcdir = os.path.join(base, _CONFIG_VARS['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': | ||||
|             kernel_version = os.uname().release  # Kernel version (8.4.3) | ||||
|             major_version = int(kernel_version.split('.')[0]) | ||||
| 
 | ||||
|             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 | ||||
|             import _osx_support | ||||
|             _osx_support.customize_config_vars(_CONFIG_VARS) | ||||
| 
 | ||||
|     if args: | ||||
|         vals = [] | ||||
|  | @ -673,8 +620,7 @@ def get_platform(): | |||
|         return sys.platform | ||||
| 
 | ||||
|     if os.name != "posix" or not hasattr(os, 'uname'): | ||||
|         # XXX what about the architecture? NT is Intel or Alpha, | ||||
|         # Mac OS is M68k or PPC, etc. | ||||
|         # XXX what about the architecture? NT is Intel or Alpha | ||||
|         return sys.platform | ||||
| 
 | ||||
|     # Set for cross builds explicitly | ||||
|  | @ -716,90 +662,10 @@ def get_platform(): | |||
|         if m: | ||||
|             release = m.group() | ||||
|     elif osname[:6] == "darwin": | ||||
|         # | ||||
|         # 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. | ||||
|         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' | ||||
|         import _osx_support | ||||
|         osname, release, machine = _osx_support.get_platform_osx( | ||||
|                                             get_config_vars(), | ||||
|                                             osname, release, machine) | ||||
| 
 | ||||
|     return "%s-%s-%s" % (osname, release, machine) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										267
									
								
								Lib/test/test__osx_support.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								Lib/test/test__osx_support.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 @@ | |||
|                        get_path, get_path_names, _INSTALL_SCHEMES, | ||||
|                        _get_default_scheme, _expand_vars, | ||||
|                        get_scheme_names, get_config_var, _main) | ||||
| import _osx_support | ||||
| 
 | ||||
| class TestSysConfig(unittest.TestCase): | ||||
| 
 | ||||
|  | @ -134,6 +135,7 @@ def test_get_platform(self): | |||
|                    ('Darwin Kernel Version 8.11.1: ' | ||||
|                     'Wed Oct 10 18:23:28 PDT 2007; ' | ||||
|                     '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()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g ' | ||||
|  | @ -152,7 +154,7 @@ def test_get_platform(self): | |||
|                    ('Darwin Kernel Version 8.11.1: ' | ||||
|                     'Wed Oct 10 18:23:28 PDT 2007; ' | ||||
|                     '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()['CFLAGS'] = ('-fno-strict-aliasing -DNDEBUG -g ' | ||||
|  | @ -167,6 +169,7 @@ def test_get_platform(self): | |||
|             sys.maxsize = maxint | ||||
| 
 | ||||
|         # 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()['CFLAGS'] = ('-arch ppc -arch i386 -isysroot ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|  | @ -175,6 +178,7 @@ def test_get_platform(self): | |||
| 
 | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|  | @ -182,18 +186,21 @@ def test_get_platform(self): | |||
| 
 | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|                                        '-dynamic -DNDEBUG -g -O3') | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|                                        '-dynamic -DNDEBUG -g -O3') | ||||
|         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 ' | ||||
|                                        '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                        '-fno-strict-aliasing -fno-common ' | ||||
|  | @ -202,6 +209,7 @@ def test_get_platform(self): | |||
|         self.assertEqual(get_platform(), 'macosx-10.4-fat64') | ||||
| 
 | ||||
|         for arch in ('ppc', 'i386', 'x86_64', 'ppc64'): | ||||
|             _osx_support._remove_original_values(get_config_vars()) | ||||
|             get_config_vars()['CFLAGS'] = ('-arch %s -isysroot ' | ||||
|                                            '/Developer/SDKs/MacOSX10.4u.sdk  ' | ||||
|                                            '-fno-strict-aliasing -fno-common ' | ||||
|  |  | |||
|  | @ -137,6 +137,11 @@ Library | |||
| - Issue 10924: Fixed mksalt() to use a RNG that is suitable for cryptographic | ||||
|   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 | ||||
| ----- | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ned Deily
						Ned Deily