[Distutils] Supporting arch specific eggs with a fat Python and setuptools

Bob Ippolito bob at redivi.com
Tue Feb 7 08:47:04 CET 2006


With the recent introduction of i386 architecture Macs, it's becoming  
a necessity to support two architectures for the platform: PPC and  
i386.  Fortunately this is done somewhat easily using Apple's GCC 4  
compiler and their linker toolchain.  Ronald and I have already  
basically made all of the necessary changes to Python (in a branch on  
another svn server) and distutils in order to make Python compile  
with multiple architectures, and to make distutils also do the right  
thing.

This solution works great (in theory and limited testing) for  
everyone except Mac OS X 10.3 users.  We have gone out of our way to  
ensure that this build of Python is compatible with Mac OS X 10.3.9  
so that those users aren't totally left in the dark, but there is a  
problem: the GCC 4 toolchain required to build extensions is not  
available to Mac OS X 10.3 users.  They simply can not build binaries  
compatible with i386.. and if they could, they couldn't link it  
together as a universal binary.  Bummer.

The workaround for this issue is to have a way to swap out the  
Makefile with a PPC-only Makefile for those users.  The problem with  
that is setuptools.  Currently setuptools doesn't include a lot of  
intelligence for choosing eggs given multiple choices.  Here's a  
scenario of various Python builds and the naming of eggs they produce:

Mac OS X 10.4 with current means:
	pysqlite-2.0.5-py2.4-macosx-10.4-ppc.egg

Mac OS X 10.3 with current means, or with the universal build and a  
swapped Makefile:
	pysqlite-2.0.5-py2.4-macosx-10.3-ppc.egg

Mac OS X 10.4 with the universal build:
	pysqlite-2.0.5-py2.4-macosx-10.3-fat.egg

The decision of which egg to choose is subjective, but the greatest  
benefit overall is achieved by choosing the maximally compatible  
version:
pysqlite-2.0.5-py2.4-macosx-10.3-fat.egg

For users of Mac OS X, here is the egg-sorting algorithm I'm  
proposing.  This sort must be used only with eggs that are compatible  
with the current architecture -- which means either "fat" or  
_macosx_arch(os.uname()[4].replace(' ', '_')).  Also allowing  
_macosx_arch and universally allowing fat are going to require  
another patch to setuptools (that I have not yet written, because  
it's not the right thing to do until egg-sorting is right).

	# a and b must only differ in platform specifics!
	def cmp_platform_eggs(a, b):
		if a.arch == "fat" and b.arch == "fat":
			pass
		elif a.arch == "fat":
			return 1
		elif b.arch == "fat":
			return -1
		# lower version sorts higher
		return -cmp(a.macosx_version, b.macosx_version)

This sort means that fat will always be preferred, and lower  
requirements sort higher.  This makes it easier for people who wish  
to redistribute self-contained applications to other users (a la  
py2app, py2exe, cx_Freeze), which is a very important use case for  
this platform.

-bob



More information about the Distutils-SIG mailing list