87
94
--third-party=DIR: Store third-party sources here (default: %(DEPSRC)r)
88
95
--sdk-path=DIR: Location of the SDK (default: %(SDKPATH)r)
89
96
--src-dir=DIR: Location of the Python sources (default: %(SRCDIR)r)
97
--dep-target=10.n OS X deployment target (default: %(DEPTARGET)r)
98
--universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r)
93
102
# Instructions for building libraries that are necessary for building a
94
103
# batteries included python.
98
url="http://www.bzip.org/1.0.3/bzip2-1.0.3.tar.gz",
100
install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
101
shellQuote(os.path.join(WORKDIR, 'libraries')),
102
' -arch '.join(ARCHLIST),
108
url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
110
install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
111
shellQuote(os.path.join(WORKDIR, 'libraries')),
112
' -arch '.join(ARCHLIST),
117
# Note that GNU readline is GPL'd software
118
name="GNU Readline 5.1.4",
119
url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" ,
122
# The readline maintainers don't do actual micro releases, but
123
# just ship a set of patches.
124
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001',
125
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002',
126
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003',
127
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004',
133
url="http://www.sqlite.org/sqlite-3.6.3.tar.gz",
134
checksum='93f742986e8bc2dfa34792e16df017a6feccf3a2',
136
'--enable-threadsafe',
137
'--enable-tempstore',
138
'--enable-shared=no',
139
'--enable-static=yes',
146
url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
151
"--without-curses-h",
154
"--datadir=/usr/share",
156
"--sharedstatedir=/usr/com",
157
"--with-terminfo-dirs=/usr/share/terminfo",
158
"--with-default-terminfo-dir=/usr/share/terminfo",
159
"--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
166
install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
167
shellQuote(os.path.join(WORKDIR, 'libraries')),
168
shellQuote(os.path.join(WORKDIR, 'libraries')),
173
name="Sleepycat DB 4.7.25",
174
url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz",
175
#name="Sleepycat DB 4.3.29",
176
#url="http://downloads.sleepycat.com/db-4.3.29.tar.gz",
177
buildDir="build_unix",
178
configure="../dist/configure",
180
'--includedir=/usr/local/include/db4',
104
# [The recipes are defined here for convenience but instantiated later after
105
# command line options have been processed.]
106
def library_recipes():
110
url="http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz",
111
checksum='fc310b254f6ba5fbb5da018f04533688',
113
install='make install PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
114
shellQuote(os.path.join(WORKDIR, 'libraries')),
115
' -arch '.join(ARCHLIST),
121
url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
122
checksum='debc62758716a169df9f62e6ab2bc634',
124
install='make install prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
125
shellQuote(os.path.join(WORKDIR, 'libraries')),
126
' -arch '.join(ARCHLIST),
131
# Note that GNU readline is GPL'd software
132
name="GNU Readline 5.1.4",
133
url="http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz" ,
134
checksum='7ee5a692db88b30ca48927a13fd60e46',
137
# The readline maintainers don't do actual micro releases, but
138
# just ship a set of patches.
139
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-001',
140
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-002',
141
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-003',
142
'http://ftp.gnu.org/pub/gnu/readline/readline-5.1-patches/readline51-004',
147
name="SQLite 3.6.11",
148
url="http://www.sqlite.org/sqlite-3.6.11.tar.gz",
149
checksum='7ebb099696ab76cc6ff65dd496d17858',
151
'--enable-threadsafe',
152
'--enable-tempstore',
153
'--enable-shared=no',
154
'--enable-static=yes',
161
url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
162
checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
167
"--without-curses-h",
170
"--datadir=/usr/share",
172
"--sharedstatedir=/usr/com",
173
"--with-terminfo-dirs=/usr/share/terminfo",
174
"--with-default-terminfo-dir=/usr/share/terminfo",
175
"--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
182
install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
183
shellQuote(os.path.join(WORKDIR, 'libraries')),
184
shellQuote(os.path.join(WORKDIR, 'libraries')),
189
name="Sleepycat DB 4.7.25",
190
url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz",
191
checksum='ec2b87e833779681a0c3a814aa71359e',
192
buildDir="build_unix",
193
configure="../dist/configure",
195
'--includedir=/usr/local/include/db4',
186
201
# Instructions for building packages inside the .mpkg.
572
602
os.makedirs(os.path.join(universal, 'usr', 'local', 'lib'))
573
603
os.makedirs(os.path.join(universal, 'usr', 'local', 'include'))
575
for recipe in LIBRARY_RECIPES:
605
for recipe in library_recipes():
576
606
buildRecipe(recipe, universal, ARCHLIST)
580
610
def buildPythonDocs():
581
# This stores the documentation as Resources/English.lproj/Docuentation
611
# This stores the documentation as Resources/English.lproj/Documentation
582
612
# inside the framwork. pydoc and IDLE will pick it up there.
583
613
print "Install python documentation"
584
614
rootDir = os.path.join(WORKDIR, '_root')
585
version = getVersion()
615
buildDir = os.path.join('../../Doc')
586
616
docdir = os.path.join(rootDir, 'pydocs')
588
novername = 'python-docs-html.tar.bz2'
589
name = 'html-%s.tar.bz2'%(getFullVersion(),)
590
sourceArchive = os.path.join(DEPSRC, name)
591
if os.path.exists(sourceArchive):
592
print "Using local copy of %s"%(name,)
595
print "Downloading %s"%(novername,)
596
downloadURL('http://www.python.org/ftp/python/doc/%s/%s'%(
597
getFullVersion(), novername), sourceArchive)
598
print "Archive for %s stored as %s"%(name, sourceArchive)
600
extractArchive(os.path.dirname(docdir), sourceArchive)
604
os.path.dirname(docdir), 'python-docs-html'),
619
runCommand('make update')
620
runCommand('make html')
622
if not os.path.exists(docdir):
624
os.rename(os.path.join(buildDir, 'build', 'html'),
625
os.path.join(docdir, 'python-docs-html'))
608
628
def buildPython():
609
print "Building a universal python"
629
print "Building a universal python for %s architectures" % UNIVERSALARCHS
611
631
buildDir = os.path.join(WORKDIR, '_bld', 'python')
612
632
rootDir = os.path.join(WORKDIR, '_root')
630
650
version = getVersion()
652
# Since the extra libs are not in their installed framework location
653
# during the build, augment the library path so that the interpreter
654
# will find them during its extension import sanity checks.
655
os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR,
656
'libraries', 'usr', 'local', 'lib')
632
657
print "Running configure..."
633
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"%(
634
shellQuote(os.path.join(SRCDIR, 'configure')),
635
shellQuote(SDKPATH), shellQuote(WORKDIR)[1:-1],
658
runCommand("%s -C --enable-framework --enable-universalsdk=%s "
659
"--with-universal-archs=%s "
660
"LDFLAGS='-g -L%s/libraries/usr/local/lib' "
661
"OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%(
662
shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH),
664
shellQuote(WORKDIR)[1:-1],
636
665
shellQuote(WORKDIR)[1:-1]))
638
667
print "Running make"
924
954
imagepath = imagepath + '.dmg'
927
runCommand("hdiutil create -volname 'Universal MacPython %s' -srcfolder %s %s"%(
957
volname='Python %s'%(getFullVersion())
958
runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%(
929
960
shellQuote(os.path.join(WORKDIR, 'installer')),
930
shellQuote(imagepath)))
961
shellQuote(imagepath + ".tmp.dmg" )))
964
if not os.path.exists(os.path.join(WORKDIR, "mnt")):
965
os.mkdir(os.path.join(WORKDIR, "mnt"))
966
runCommand("hdiutil attach %s -mountroot %s"%(
967
shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt"))))
969
# Custom icon for the DMG, shown when the DMG is mounted.
970
shutil.copy("../Icons/Disk Image.icns",
971
os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns"))
972
runCommand("/Developer/Tools/SetFile -a C %s/"%(
973
shellQuote(os.path.join(WORKDIR, "mnt", volname)),))
975
runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname))))
977
setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns")
978
runCommand("hdiutil convert %s -format UDZO -o %s"%(
979
shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath)))
980
setIcon(imagepath, "../Icons/Disk Image.icns")
982
os.unlink(imagepath + ".tmp.dmg")
935
987
def setIcon(filePath, icnsPath):
937
989
Set the custom icon for the specified file or directory.
939
For a directory the icon data is written in a file named 'Icon\r' inside
940
the directory. For both files and directories write the icon as an 'icns'
941
resource. Furthermore set kHasCustomIcon in the finder flags for filePath.
943
ref, isDirectory = Carbon.File.FSPathMakeRef(icnsPath)
944
icon = Carbon.Icn.ReadIconFile(ref)
948
# Open the resource fork of the target, to add the icon later on.
949
# For directories we use the file 'Icon\r' inside the directory.
952
ref, isDirectory = Carbon.File.FSPathMakeRef(filePath)
955
# There is a problem with getting this into the pax(1) archive,
956
# just ignore directory icons for now.
959
tmpPath = os.path.join(filePath, "Icon\r")
960
if not os.path.exists(tmpPath):
961
fp = open(tmpPath, 'w')
964
tmpRef, _ = Carbon.File.FSPathMakeRef(tmpPath)
965
spec = Carbon.File.FSSpec(tmpRef)
968
spec = Carbon.File.FSSpec(ref)
971
Carbon.Res.HCreateResFile(*spec.as_tuple())
975
# Try to create the resource fork again, this will avoid problems
976
# when adding an icon to a directory. I have no idea why this helps,
977
# but without this adding the icon to a directory will fail sometimes.
979
Carbon.Res.HCreateResFile(*spec.as_tuple())
983
refNum = Carbon.Res.FSpOpenResFile(spec, fsRdWrPerm)
985
Carbon.Res.UseResFile(refNum)
987
# Check if there already is an icon, remove it if there is.
989
h = Carbon.Res.Get1Resource('icns', kCustomIconResource)
997
# Add the icon to the resource for of the target
998
res = Carbon.Res.Resource(icon)
999
res.AddResource('icns', kCustomIconResource, '')
1001
res.DetachResource()
1002
Carbon.Res.CloseResFile(refNum)
1004
# And now set the kHasCustomIcon property for the target. Annoyingly,
1005
# python doesn't seem to have bindings for the API that is needed for
1006
# this. Cop out and call SetFile
1007
os.system("/Developer/Tools/SetFile -a C %s"%(
1008
shellQuote(filePath),))
1011
os.system('/Developer/Tools/SetFile -a V %s'%(
1012
shellQuote(tmpPath),
992
toolPath = os.path.join(os.path.dirname(__file__), "seticon.app/Contents/MacOS/seticon")
993
dirPath = os.path.dirname(__file__)
994
if not os.path.exists(toolPath) or os.stat(toolPath).st_mtime < os.stat(dirPath + '/seticon.m').st_mtime:
995
# NOTE: The tool is created inside an .app bundle, otherwise it won't work due
996
# to connections to the window server.
997
if not os.path.exists('seticon.app/Contents/MacOS'):
998
os.makedirs('seticon.app/Contents/MacOS')
999
runCommand("cc -o %s %s/seticon.m -framework Cocoa"%(
1000
shellQuote(toolPath), shellQuote(dirPath)))
1002
runCommand("%s %s %s"%(shellQuote(os.path.abspath(toolPath)), shellQuote(icnsPath),
1003
shellQuote(filePath)))
1016
1006
# First parse options and check if we can perform our work
1018
1008
checkEnvironment()
1020
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.3'
1010
os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET
1022
1012
if os.path.exists(WORKDIR):
1023
1013
shutil.rmtree(WORKDIR)