summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonald Oussoren <ronaldoussoren@mac.com>2009-03-30 19:34:51 (GMT)
committerRonald Oussoren <ronaldoussoren@mac.com>2009-03-30 19:34:51 (GMT)
commit508282e8974c182c2240a9df5d8fd8493f75be20 (patch)
treecf8ba685d7de1c84c2054fe38a1741e11a4faa5f
parent451e82439dee0bb9b9408ad39409edf594f0a93b (diff)
downloadcpython-508282e8974c182c2240a9df5d8fd8493f75be20.zip
cpython-508282e8974c182c2240a9df5d8fd8493f75be20.tar.gz
cpython-508282e8974c182c2240a9df5d8fd8493f75be20.tar.bz2
* Set a custom icon on the Python installer DMG
* Remove last traces of "MacPython" * Add options to build different flavors of the installer (still defaulting to a 2-way universal build that runs on OSX 10.3)
-rw-r--r--Mac/BuildScript/README.txt11
-rwxr-xr-xMac/BuildScript/build-installer.py305
2 files changed, 189 insertions, 127 deletions
diff --git a/Mac/BuildScript/README.txt b/Mac/BuildScript/README.txt
index 41df0e4..0f1aeb5 100644
--- a/Mac/BuildScript/README.txt
+++ b/Mac/BuildScript/README.txt
@@ -37,6 +37,17 @@ Here are the steps you need to follow to build a MacPython installer:
* When done the script will tell you where the DMG image is (by default
somewhere in ``/tmp/_py``).
+Building a 4-way universal installer
+....................................
+
+It is also possible to build a 4-way universal installer that runs on
+OSX Leopard or later::
+
+ $ ./build-installer.py --dep-target=10.5 --universal-archs=all --sdk=/
+
+This requires that the deployment target is 10.5 (or later), and hence
+also that your building on at least OSX 10.5.
+
Testing
-------
diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py
index 8051256..c2cdb02 100755
--- a/Mac/BuildScript/build-installer.py
+++ b/Mac/BuildScript/build-installer.py
@@ -2,7 +2,8 @@
"""
This script is used to build the "official unofficial" universal build on
Mac OS X. It requires Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK to do its
-work.
+work. 64-bit or four-way universal builds require at least OS X 10.5 and
+the 10.5 SDK.
Please ensure that this script keeps working with Python 2.3, to avoid
bootstrap issues (/usr/bin/python is Python 2.3 on OSX 10.4)
@@ -63,7 +64,15 @@ DEPSRC = os.path.expanduser('~/Universal/other-sources')
SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk"
#SDKPATH = "/"
-ARCHLIST = ('i386', 'ppc',)
+universal_opts_map = { '32-bit': ('i386', 'ppc',),
+ '64-bit': ('x86_64', 'ppc64',),
+ 'all': ('i386', 'ppc', 'x86_64', 'ppc64',) }
+
+UNIVERSALOPTS = tuple(universal_opts_map.keys())
+
+UNIVERSALARCHS = '32-bit'
+
+ARCHLIST = universal_opts_map[UNIVERSALARCHS]
# Source directory (asume we're in Mac/BuildScript)
SRCDIR = os.path.dirname(
@@ -72,6 +81,9 @@ SRCDIR = os.path.dirname(
os.path.abspath(__file__
))))
+# $MACOSX_DEPLOYMENT_TARGET -> minimum OS X level
+DEPTARGET = '10.3'
+
USAGE = textwrap.dedent("""\
Usage: build_python [options]
@@ -82,103 +94,108 @@ USAGE = textwrap.dedent("""\
--third-party=DIR: Store third-party sources here (default: %(DEPSRC)r)
--sdk-path=DIR: Location of the SDK (default: %(SDKPATH)r)
--src-dir=DIR: Location of the Python sources (default: %(SRCDIR)r)
+ --dep-target=10.n OS X deployment target (default: %(DEPTARGET)r)
+ --universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r)
""")% globals()
# Instructions for building libraries that are necessary for building a
# batteries included python.
-LIBRARY_RECIPES = [
- dict(
- name="Bzip2 1.0.4",
- url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz",
- checksum='fc310b254f6ba5fbb5da018f04533688',
- configure=None,
- install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
- shellQuote(os.path.join(WORKDIR, 'libraries')),
- ' -arch '.join(ARCHLIST),
- SDKPATH,
- ),
- ),
- dict(
- name="ZLib 1.2.3",
- url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
- checksum='debc62758716a169df9f62e6ab2bc634',
- configure=None,
- install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
- shellQuote(os.path.join(WORKDIR, 'libraries')),
- ' -arch '.join(ARCHLIST),
- SDKPATH,
- ),
- ),
- dict(
- # Note that GNU readline is GPL'd software
- name="GNU Readline 5.1.4",
- url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" ,
- checksum='7ee5a692db88b30ca48927a13fd60e46',
- patchlevel='0',
- patches=[
- # The readline maintainers don't do actual micro releases, but
- # just ship a set of patches.
- 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001',
- 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002',
- 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003',
- 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004',
- ]
- ),
-
- dict(
- name="SQLite 3.6.11",
- url="http://www.sqlite.org/sqlite-3.6.11.tar.gz",
- checksum='7ebb099696ab76cc6ff65dd496d17858',
- configure_pre=[
- '--enable-threadsafe',
- '--enable-tempstore',
- '--enable-shared=no',
- '--enable-static=yes',
- '--disable-tcl',
- ]
- ),
-
- dict(
- name="NCurses 5.5",
- url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
- checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
- configure_pre=[
- "--without-cxx",
- "--without-ada",
- "--without-progs",
- "--without-curses-h",
- "--enable-shared",
- "--with-shared",
- "--datadir=/usr/share",
- "--sysconfdir=/etc",
- "--sharedstatedir=/usr/com",
- "--with-terminfo-dirs=/usr/share/terminfo",
- "--with-default-terminfo-dir=/usr/share/terminfo",
- "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
- "--enable-termcap",
- ],
- patches=[
- "ncurses-5.5.patch",
- ],
- useLDFlags=False,
- install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
- shellQuote(os.path.join(WORKDIR, 'libraries')),
- shellQuote(os.path.join(WORKDIR, 'libraries')),
- getVersion(),
- ),
- ),
- dict(
- name="Sleepycat DB 4.7.25",
- url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz",
- checksum='ec2b87e833779681a0c3a814aa71359e',
- buildDir="build_unix",
- configure="../dist/configure",
- configure_pre=[
- '--includedir=/usr/local/include/db4',
- ]
- ),
-]
+# [The recipes are defined here for convenience but instantiated later after
+# command line options have been processed.]
+def library_recipes():
+ return [
+ dict(
+ name="Bzip2 1.0.4",
+ url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz",
+ checksum='fc310b254f6ba5fbb5da018f04533688',
+ configure=None,
+ install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
+ shellQuote(os.path.join(WORKDIR, 'libraries')),
+ ' -arch '.join(ARCHLIST),
+ SDKPATH,
+ ),
+ ),
+ dict(
+ name="ZLib 1.2.3",
+ url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
+ checksum='debc62758716a169df9f62e6ab2bc634',
+ configure=None,
+ install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
+ shellQuote(os.path.join(WORKDIR, 'libraries')),
+ ' -arch '.join(ARCHLIST),
+ SDKPATH,
+ ),
+ ),
+ dict(
+ # Note that GNU readline is GPL'd software
+ name="GNU Readline 5.1.4",
+ url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" ,
+ checksum='7ee5a692db88b30ca48927a13fd60e46',
+ patchlevel='0',
+ patches=[
+ # The readline maintainers don't do actual micro releases, but
+ # just ship a set of patches.
+ 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001',
+ 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002',
+ 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003',
+ 'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004',
+ ]
+ ),
+
+ dict(
+ name="SQLite 3.6.11",
+ url="http://www.sqlite.org/sqlite-3.6.11.tar.gz",
+ checksum='7ebb099696ab76cc6ff65dd496d17858',
+ configure_pre=[
+ '--enable-threadsafe',
+ '--enable-tempstore',
+ '--enable-shared=no',
+ '--enable-static=yes',
+ '--disable-tcl',
+ ]
+ ),
+
+ dict(
+ name="NCurses 5.5",
+ url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
+ checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
+ configure_pre=[
+ "--without-cxx",
+ "--without-ada",
+ "--without-progs",
+ "--without-curses-h",
+ "--enable-shared",
+ "--with-shared",
+ "--datadir=/usr/share",
+ "--sysconfdir=/etc",
+ "--sharedstatedir=/usr/com",
+ "--with-terminfo-dirs=/usr/share/terminfo",
+ "--with-default-terminfo-dir=/usr/share/terminfo",
+ "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
+ "--enable-termcap",
+ ],
+ patches=[
+ "ncurses-5.5.patch",
+ ],
+ useLDFlags=False,
+ install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
+ shellQuote(os.path.join(WORKDIR, 'libraries')),
+ shellQuote(os.path.join(WORKDIR, 'libraries')),
+ getVersion(),
+ ),
+ ),
+ dict(
+ name="Sleepycat DB 4.7.25",
+ url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz",
+ checksum='ec2b87e833779681a0c3a814aa71359e',
+ buildDir="build_unix",
+ configure="../dist/configure",
+ configure_pre=[
+ '--includedir=/usr/local/include/db4',
+ ]
+ ),
+ ]
# Instructions for building packages inside the .mpkg.
@@ -213,8 +230,8 @@ PKG_RECIPES = [
source="/usr/local/bin",
readme="""\
This package installs the unix tools in /usr/local/bin for
- compatibility with older releases of MacPython. This package
- is not necessary to use MacPython.
+ compatibility with older releases of Python. This package
+ is not necessary to use Python.
""",
required=False,
),
@@ -237,7 +254,7 @@ PKG_RECIPES = [
long_name="Shell profile updater",
readme="""\
This packages updates your shell profile to make sure that
- the MacPython tools are found by your shell in preference of
+ the Python tools are found by your shell in preference of
the system provided Python tools.
If you don't install this package you'll have to add
@@ -325,14 +342,16 @@ def parseOptions(args=None):
"""
Parse arguments and update global settings.
"""
- global WORKDIR, DEPSRC, SDKPATH, SRCDIR
+ global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET
+ global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST
if args is None:
args = sys.argv[1:]
try:
options, args = getopt.getopt(args, '?hb',
- [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir='])
+ [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=',
+ 'dep-target=', 'universal-archs=', 'help' ])
except getopt.error, msg:
print msg
sys.exit(1)
@@ -342,7 +361,7 @@ def parseOptions(args=None):
sys.exit(1)
for k, v in options:
- if k in ('-h', '-?'):
+ if k in ('-h', '-?', '--help'):
print USAGE
sys.exit(0)
@@ -358,6 +377,16 @@ def parseOptions(args=None):
elif k in ('--src-dir',):
SRCDIR=v
+ elif k in ('--dep-target', ):
+ DEPTARGET=v
+
+ elif k in ('--universal-archs', ):
+ if v in UNIVERSALOPTS:
+ UNIVERSALARCHS = v
+ ARCHLIST = universal_opts_map[UNIVERSALARCHS]
+ else:
+ raise NotImplementedError, v
+
else:
raise NotImplementedError, k
@@ -370,7 +399,9 @@ def parseOptions(args=None):
print " * Source directory:", SRCDIR
print " * Build directory: ", WORKDIR
print " * SDK location: ", SDKPATH
- print " * third-party source:", DEPSRC
+ print " * Third-party source:", DEPSRC
+ print " * Deployment target:", DEPTARGET
+ print " * Universal architectures:", ARCHLIST
print ""
@@ -480,6 +511,7 @@ def buildRecipe(recipe, basedir, archList):
print "Using local copy of %s"%(name,)
else:
+ print "Did not find local copy of %s"%(name,)
print "Downloading %s"%(name,)
downloadURL(url, sourceArchive)
print "Archive for %s stored as %s"%(name, sourceArchive)
@@ -570,7 +602,7 @@ def buildLibraries():
os.makedirs(os.path.join(universal, 'usr', 'local', 'lib'))
os.makedirs(os.path.join(universal, 'usr', 'local', 'include'))
- for recipe in LIBRARY_RECIPES:
+ for recipe in library_recipes():
buildRecipe(recipe, universal, ARCHLIST)
@@ -594,7 +626,7 @@ def buildPythonDocs():
def buildPython():
- print "Building a universal python"
+ print "Building a universal python for %s architectures" % UNIVERSALARCHS
buildDir = os.path.join(WORKDIR, '_bld', 'python')
rootDir = os.path.join(WORKDIR, '_root')
@@ -618,9 +650,13 @@ def buildPython():
version = getVersion()
print "Running configure..."
- runCommand("%s -C --enable-framework --enable-universalsdk=%s LDFLAGS='-g -L%s/libraries/usr/local/lib' OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%(
- shellQuote(os.path.join(SRCDIR, 'configure')),
- shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1],
+ runCommand("%s -C --enable-framework --enable-universalsdk=%s "
+ "--with-universal-archs=%s "
+ "LDFLAGS='-g -L%s/libraries/usr/local/lib' "
+ "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%(
+ shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH),
+ UNIVERSALARCHS,
+ shellQuote(WORKDIR)[1:-1],
shellQuote(WORKDIR)[1:-1]))
print "Running make"
@@ -701,7 +737,7 @@ def patchFile(inPath, outPath):
data = fileContents(inPath)
data = data.replace('$FULL_VERSION', getFullVersion())
data = data.replace('$VERSION', getVersion())
- data = data.replace('$MACOSX_DEPLOYMENT_TARGET', '10.3 or later')
+ data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later')))
data = data.replace('$ARCHITECTURES', "i386, ppc")
data = data.replace('$INSTALL_SIZE', installSize())
@@ -781,9 +817,9 @@ def packageFromRecipe(targetDir, recipe):
vers = getFullVersion()
major, minor = map(int, getVersion().split('.', 2))
pl = Plist(
- CFBundleGetInfoString="MacPython.%s %s"%(pkgname, vers,),
- CFBundleIdentifier='org.python.MacPython.%s'%(pkgname,),
- CFBundleName='MacPython.%s'%(pkgname,),
+ CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,),
+ CFBundleIdentifier='org.python.Python.%s'%(pkgname,),
+ CFBundleName='Python.%s'%(pkgname,),
CFBundleShortVersionString=vers,
IFMajorVersion=major,
IFMinorVersion=minor,
@@ -804,7 +840,7 @@ def packageFromRecipe(targetDir, recipe):
pl = Plist(
IFPkgDescriptionDescription=readme,
- IFPkgDescriptionTitle=recipe.get('long_name', "MacPython.%s"%(pkgname,)),
+ IFPkgDescriptionTitle=recipe.get('long_name', "Python.%s"%(pkgname,)),
IFPkgDescriptionVersion=vers,
)
writePlist(pl, os.path.join(packageContents, 'Resources', 'Description.plist'))
@@ -819,9 +855,9 @@ def makeMpkgPlist(path):
major, minor = map(int, getVersion().split('.', 2))
pl = Plist(
- CFBundleGetInfoString="MacPython %s"%(vers,),
- CFBundleIdentifier='org.python.MacPython',
- CFBundleName='MacPython',
+ CFBundleGetInfoString="Python %s"%(vers,),
+ CFBundleIdentifier='org.python.Python',
+ CFBundleName='Python',
CFBundleShortVersionString=vers,
IFMajorVersion=major,
IFMinorVersion=minor,
@@ -855,7 +891,7 @@ def buildInstaller():
shutil.rmtree(outdir)
os.mkdir(outdir)
- pkgroot = os.path.join(outdir, 'MacPython.mpkg', 'Contents')
+ pkgroot = os.path.join(outdir, 'Python.mpkg', 'Contents')
pkgcontents = os.path.join(pkgroot, 'Packages')
os.makedirs(pkgcontents)
for recipe in PKG_RECIPES:
@@ -872,7 +908,7 @@ def buildInstaller():
makeMpkgPlist(os.path.join(pkgroot, 'Info.plist'))
pl = Plist(
- IFPkgDescriptionTitle="Universal MacPython",
+ IFPkgDescriptionTitle="Python",
IFPkgDescriptionVersion=getVersion(),
)
@@ -912,10 +948,32 @@ def buildDMG():
imagepath = imagepath + '.dmg'
os.mkdir(outdir)
- runCommand("hdiutil create -volname 'Universal MacPython %s' -srcfolder %s %s"%(
- getFullVersion(),
+ volname='Python %s'%(getFullVersion())
+ runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%(
+ shellQuote(volname),
shellQuote(os.path.join(WORKDIR, 'installer')),
- shellQuote(imagepath)))
+ shellQuote(imagepath + ".tmp.dmg" )))
+
+
+ if not os.path.exists(os.path.join(WORKDIR, "mnt")):
+ os.mkdir(os.path.join(WORKDIR, "mnt"))
+ runCommand("hdiutil attach %s -mountroot %s"%(
+ shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt"))))
+
+ # Custom icon for the DMG, shown when the DMG is mounted.
+ shutil.copy("../Icons/Disk Image.icns",
+ os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns"))
+ runCommand("/Developer/Tools/SetFile -a C %s/"%(
+ shellQuote(os.path.join(WORKDIR, "mnt", volname)),))
+
+ runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname))))
+
+ setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns")
+ runCommand("hdiutil convert %s -format UDZO -o %s"%(
+ shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath)))
+ setIcon(imagepath, "../Icons/Disk Image.icns")
+
+ os.unlink(imagepath + ".tmp.dmg")
return imagepath
@@ -943,7 +1001,7 @@ def main():
parseOptions()
checkEnvironment()
- os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
+ os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET
if os.path.exists(WORKDIR):
shutil.rmtree(WORKDIR)
@@ -979,13 +1037,6 @@ def main():
print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos
fp.close()
- # Custom icon for the DMG, shown when the DMG is mounted.
- # XXX: Code is diabled because it doesn't actually work :-(
-# shutil.copy("../Icons/Disk Image.icns",
-# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns"))
-# os.system("/Developer/Tools/SetFile -a C %s"%(
-# os.path.join(WORKDIR, "installer", ".VolumeIcon.icns")))
- setIcon(os.path.join(WORKDIR, "installer"), "../Icons/Disk Image.icns")
# And copy it to a DMG