@@ -162,7 +162,7 @@ def get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
162162 "I don't know where Python installs its library "
163163 "on platform '%s'" % os .name )
164164
165- _USE_CLANG = None
165+
166166
167167def customize_compiler (compiler ):
168168 """Do any platform-specific customization of a CCompiler instance.
@@ -177,36 +177,7 @@ def customize_compiler(compiler):
177177
178178 newcc = None
179179 if 'CC' in os .environ :
180- newcc = os .environ ['CC' ]
181- elif sys .platform == 'darwin' and cc == 'gcc-4.2' :
182- # Issue #13590:
183- # Since Apple removed gcc-4.2 in Xcode 4.2, we can no
184- # longer assume it is available for extension module builds.
185- # If Python was built with gcc-4.2, check first to see if
186- # it is available on this system; if not, try to use clang
187- # instead unless the caller explicitly set CC.
188- global _USE_CLANG
189- if _USE_CLANG is None :
190- from distutils import log
191- from subprocess import Popen , PIPE
192- p = Popen ("! type gcc-4.2 && type clang && exit 2" ,
193- shell = True , stdout = PIPE , stderr = PIPE )
194- p .wait ()
195- if p .returncode == 2 :
196- _USE_CLANG = True
197- log .warn ("gcc-4.2 not found, using clang instead" )
198- else :
199- _USE_CLANG = False
200- if _USE_CLANG :
201- newcc = 'clang'
202- if newcc :
203- # On OS X, if CC is overridden, use that as the default
204- # command for LDSHARED as well
205- if (sys .platform == 'darwin'
206- and 'LDSHARED' not in os .environ
207- and ldshared .startswith (cc )):
208- ldshared = newcc + ldshared [len (cc ):]
209- cc = newcc
180+ cc = os .environ ['CC' ]
210181 if 'CXX' in os .environ :
211182 cxx = os .environ ['CXX' ]
212183 if 'LDSHARED' in os .environ :
@@ -522,6 +493,29 @@ def _init_os2():
522493 _config_vars = g
523494
524495
496+ def _read_output (commandstring ):
497+ """
498+ Returns os.popen(commandstring, "r").read(), but
499+ without actually using os.popen because that
500+ function is not usable during python bootstrap
501+ """
502+ # NOTE: tempfile is also not useable during
503+ # bootstrap
504+ import contextlib
505+ try :
506+ import tempfile
507+ fp = tempfile .NamedTemporaryFile ()
508+ except ImportError :
509+ fp = open ("/tmp/distutils.%s" % (
510+ os .getpid (),), "w+b" )
511+
512+ with contextlib .closing (fp ) as fp :
513+ cmd = "%s >'%s'" % (commandstring , fp .name )
514+ os .system (cmd )
515+ data = fp .read ()
516+
517+ return data .decode ('utf-8' )
518+
525519def get_config_vars (* args ):
526520 """With no arguments, return a dictionary of all configuration
527521 variables relevant for the current platform. Generally this includes
@@ -561,9 +555,70 @@ def get_config_vars(*args):
561555 _config_vars ['srcdir' ] = os .path .normpath (srcdir )
562556
563557 if sys .platform == 'darwin' :
558+ from distutils .spawn import find_executable
559+
564560 kernel_version = os .uname ()[2 ] # Kernel version (8.4.3)
565561 major_version = int (kernel_version .split ('.' )[0 ])
566562
563+ # Issue #13590:
564+ # The OSX location for the compiler varies between OSX
565+ # (or rather Xcode) releases. With older releases (up-to 10.5)
566+ # the compiler is in /usr/bin, with newer releases the compiler
567+ # can only be found inside Xcode.app if the "Command Line Tools"
568+ # are not installed.
569+ #
570+ # Futhermore, the compiler that can be used varies between
571+ # Xcode releases. Upto Xcode 4 it was possible to use 'gcc-4.2'
572+ # as the compiler, after that 'clang' should be used because
573+ # gcc-4.2 is either not present, or a copy of 'llvm-gcc' that
574+ # miscompiles Python.
575+
576+ # skip checks if the compiler was overriden with a CC env variable
577+ if 'CC' not in os .environ :
578+ cc = oldcc = _config_vars ['CC' ]
579+ if not find_executable (cc ):
580+ # Compiler is not found on the shell search PATH.
581+ # Now search for clang, first on PATH (if the Command LIne
582+ # Tools have been installed in / or if the user has provided
583+ # another location via CC). If not found, try using xcrun
584+ # to find an uninstalled clang (within a selected Xcode).
585+
586+ # NOTE: Cannot use subprocess here because of bootstrap
587+ # issues when building Python itself (and os.popen is
588+ # implemented on top of subprocess and is therefore not
589+ # usable as well)
590+
591+ data = (find_executable ('clang' ) or
592+ _read_output (
593+ "/usr/bin/xcrun -find clang 2>/dev/null" ).strip ())
594+ if not data :
595+ raise DistutilsPlatformError (
596+ "Cannot locate working compiler" )
597+
598+ _config_vars ['CC' ] = cc = data
599+ _config_vars ['CXX' ] = cc + '++'
600+
601+ elif os .path .basename (cc ).startswith ('gcc' ):
602+ # Compiler is GCC, check if it is LLVM-GCC
603+ data = _read_output ("'%s' --version 2>/dev/null"
604+ % (cc .replace ("'" , "'\" '\" '" ),))
605+ if 'llvm-gcc' in data :
606+ # Found LLVM-GCC, fall back to clang
607+ data = (find_executable ('clang' ) or
608+ _read_output (
609+ "/usr/bin/xcrun -find clang 2>/dev/null" ).strip ())
610+ if find_executable (data ):
611+ _config_vars ['CC' ] = cc = data
612+ _config_vars ['CXX' ] = cc + '++'
613+
614+ if (cc != oldcc
615+ and 'LDSHARED' in _config_vars
616+ and 'LDSHARED' not in os .environ ):
617+ # modify LDSHARED if we modified CC
618+ ldshared = _config_vars ['LDSHARED' ]
619+ if ldshared .startswith (oldcc ):
620+ _config_vars ['LDSHARED' ] = cc + ldshared [len (oldcc ):]
621+
567622 if major_version < 8 :
568623 # On Mac OS X before 10.4, check if -arch and -isysroot
569624 # are in CFLAGS or LDFLAGS and remove them if they are.
@@ -579,19 +634,45 @@ def get_config_vars(*args):
579634 _config_vars [key ] = flags
580635
581636 else :
637+ # Different Xcode releases support different sets for '-arch'
638+ # flags. In particular, Xcode 4.x no longer supports the
639+ # PPC architectures.
640+ #
641+ # This code automatically removes '-arch ppc' and '-arch ppc64'
642+ # when these are not supported. That makes it possible to
643+ # build extensions on OSX 10.7 and later with the prebuilt
644+ # 32-bit installer on the python.org website.
645+ flags = _config_vars ['CFLAGS' ]
646+ if re .search ('-arch\s+ppc' , flags ) is not None :
647+ # NOTE: Cannot use subprocess here because of bootstrap
648+ # issues when building Python itself
649+ status = os .system ("'%s' -arch ppc -x c /dev/null 2>/dev/null" % (
650+ _config_vars ['CC' ].replace ("'" , "'\" '\" '" ),))
651+
652+ if status != 0 :
653+ # Compiler doesn't support PPC, remove the related
654+ # '-arch' flags.
655+ for key in ('LDFLAGS' , 'BASECFLAGS' ,
656+ # a number of derived variables. These need to be
657+ # patched up as well.
658+ 'CFLAGS' , 'PY_CFLAGS' , 'BLDSHARED' , 'LDSHARED' ):
659+
660+ flags = _config_vars [key ]
661+ flags = re .sub ('-arch\s+ppc\w*\s' , ' ' , flags )
662+ _config_vars [key ] = flags
663+
582664
583665 # Allow the user to override the architecture flags using
584666 # an environment variable.
585667 # NOTE: This name was introduced by Apple in OSX 10.5 and
586668 # is used by several scripting languages distributed with
587669 # that OS release.
588-
589670 if 'ARCHFLAGS' in os .environ :
590671 arch = os .environ ['ARCHFLAGS' ]
591672 for key in ('LDFLAGS' , 'BASECFLAGS' ,
592673 # a number of derived variables. These need to be
593674 # patched up as well.
594- 'CFLAGS' , 'PY_CFLAGS' , 'BLDSHARED' ):
675+ 'CFLAGS' , 'PY_CFLAGS' , 'BLDSHARED' , 'LDSHARED' ):
595676
596677 flags = _config_vars [key ]
597678 flags = re .sub ('-arch\s+\w+\s' , ' ' , flags )
0 commit comments