Back to index

python3.2  3.2.2
Functions | Variables
build-installer Namespace Reference

Functions

def writePlist
def shellQuote
def grepValue
def getVersion
def getVersionTuple
def getFullVersion
def library_recipes
def pkg_recipes
def fatal
def fileContents
def runCommand
def captureCommand
def getTclTkVersion
def checkEnvironment
def parseOptions
def extractArchive
def downloadURL
def buildRecipe
def buildLibraries
def buildPythonDocs
def buildPython
def patchFile
def patchScript
def packageFromRecipe
def makeMpkgPlist
def buildInstaller
def installSize
def buildDMG
def setIcon
def main

Variables

int INCLUDE_TIMESTAMP = 1
int VERBOSE = 1
string WORKDIR = "/tmp/_py"
tuple DEPSRC = os.path.join(WORKDIR, 'third-party')
string SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk"
 There are some issues with the SDK selection below here, The resulting binary doesn't work on all platforms that it should.
dictionary universal_opts_map
dictionary default_target_map
tuple UNIVERSALOPTS = tuple(universal_opts_map.keys())
string UNIVERSALARCHS = '32-bit'
list ARCHLIST = universal_opts_map[UNIVERSALARCHS]
tuple SRCDIR
string DEPTARGET = '10.3'
dictionary target_cc_map
list CC = target_cc_map[DEPTARGET]
tuple PYTHON_3 = getVersionTuple()
tuple USAGE
dictionary KNOWNSIZES

Function Documentation

def build-installer.buildDMG ( )
Create DMG containing the rootDir.

Definition at line 1100 of file build-installer.py.

01100 
01101 def buildDMG():
01102     """
01103     Create DMG containing the rootDir.
01104     """
01105     outdir = os.path.join(WORKDIR, 'diskimage')
01106     if os.path.exists(outdir):
01107         shutil.rmtree(outdir)
01108 
01109     imagepath = os.path.join(outdir,
01110                     'python-%s-macosx%s'%(getFullVersion(),DEPTARGET))
01111     if INCLUDE_TIMESTAMP:
01112         imagepath = imagepath + '-%04d-%02d-%02d'%(time.localtime()[:3])
01113     imagepath = imagepath + '.dmg'
01114 
01115     os.mkdir(outdir)
01116     volname='Python %s'%(getFullVersion())
01117     runCommand("hdiutil create -format UDRW -volname %s -srcfolder %s %s"%(
01118             shellQuote(volname),
01119             shellQuote(os.path.join(WORKDIR, 'installer')),
01120             shellQuote(imagepath + ".tmp.dmg" )))
01121 
01122 
01123     if not os.path.exists(os.path.join(WORKDIR, "mnt")):
01124         os.mkdir(os.path.join(WORKDIR, "mnt"))
01125     runCommand("hdiutil attach %s -mountroot %s"%(
01126         shellQuote(imagepath + ".tmp.dmg"), shellQuote(os.path.join(WORKDIR, "mnt"))))
01127 
01128     # Custom icon for the DMG, shown when the DMG is mounted.
01129     shutil.copy("../Icons/Disk Image.icns",
01130             os.path.join(WORKDIR, "mnt", volname, ".VolumeIcon.icns"))
01131     runCommand("/Developer/Tools/SetFile -a C %s/"%(
01132             shellQuote(os.path.join(WORKDIR, "mnt", volname)),))
01133 
01134     runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname))))
01135 
01136     setIcon(imagepath + ".tmp.dmg", "../Icons/Disk Image.icns")
01137     runCommand("hdiutil convert %s -format UDZO -o %s"%(
01138             shellQuote(imagepath + ".tmp.dmg"), shellQuote(imagepath)))
01139     setIcon(imagepath, "../Icons/Disk Image.icns")
01140 
01141     os.unlink(imagepath + ".tmp.dmg")
01142 
01143     return imagepath
01144 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.buildInstaller ( )

Definition at line 1045 of file build-installer.py.

01045 
01046 def buildInstaller():
01047 
01048     # Zap all compiled files
01049     for dirpath, _, filenames in os.walk(os.path.join(WORKDIR, '_root')):
01050         for fn in filenames:
01051             if fn.endswith('.pyc') or fn.endswith('.pyo'):
01052                 os.unlink(os.path.join(dirpath, fn))
01053 
01054     outdir = os.path.join(WORKDIR, 'installer')
01055     if os.path.exists(outdir):
01056         shutil.rmtree(outdir)
01057     os.mkdir(outdir)
01058 
01059     pkgroot = os.path.join(outdir, 'Python.mpkg', 'Contents')
01060     pkgcontents = os.path.join(pkgroot, 'Packages')
01061     os.makedirs(pkgcontents)
01062     for recipe in pkg_recipes():
01063         packageFromRecipe(pkgcontents, recipe)
01064 
01065     rsrcDir = os.path.join(pkgroot, 'Resources')
01066 
01067     fn = os.path.join(pkgroot, 'PkgInfo')
01068     fp = open(fn, 'w')
01069     fp.write('pmkrpkg1')
01070     fp.close()
01071 
01072     os.mkdir(rsrcDir)
01073 
01074     makeMpkgPlist(os.path.join(pkgroot, 'Info.plist'))
01075     pl = Plist(
01076                 IFPkgDescriptionTitle="Python",
01077                 IFPkgDescriptionVersion=getVersion(),
01078             )
01079 
01080     writePlist(pl, os.path.join(pkgroot, 'Resources', 'Description.plist'))
01081     for fn in os.listdir('resources'):
01082         if fn == '.svn': continue
01083         if fn.endswith('.jpg'):
01084             shutil.copy(os.path.join('resources', fn), os.path.join(rsrcDir, fn))
01085         else:
01086             patchFile(os.path.join('resources', fn), os.path.join(rsrcDir, fn))
01087 
01088     shutil.copy("../../LICENSE", os.path.join(rsrcDir, 'License.txt'))
01089 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.buildLibraries ( )
Build our dependencies into $WORKDIR/libraries/usr/local

Definition at line 725 of file build-installer.py.

00725 
00726 def buildLibraries():
00727     """
00728     Build our dependencies into $WORKDIR/libraries/usr/local
00729     """
00730     print ""
00731     print "Building required libraries"
00732     print ""
00733     universal = os.path.join(WORKDIR, 'libraries')
00734     os.mkdir(universal)
00735     os.makedirs(os.path.join(universal, 'usr', 'local', 'lib'))
00736     os.makedirs(os.path.join(universal, 'usr', 'local', 'include'))
00737 
00738     for recipe in library_recipes():
00739         buildRecipe(recipe, universal, ARCHLIST)
00740 
00741 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.buildPython ( )

Definition at line 759 of file build-installer.py.

00759 
00760 def buildPython():
00761     print "Building a universal python for %s architectures" % UNIVERSALARCHS
00762 
00763     buildDir = os.path.join(WORKDIR, '_bld', 'python')
00764     rootDir = os.path.join(WORKDIR, '_root')
00765 
00766     if os.path.exists(buildDir):
00767         shutil.rmtree(buildDir)
00768     if os.path.exists(rootDir):
00769         shutil.rmtree(rootDir)
00770     os.makedirs(buildDir)
00771     os.makedirs(rootDir)
00772     os.makedirs(os.path.join(rootDir, 'empty-dir'))
00773     curdir = os.getcwd()
00774     os.chdir(buildDir)
00775 
00776     # Not sure if this is still needed, the original build script
00777     # claims that parts of the install assume python.exe exists.
00778     os.symlink('python', os.path.join(buildDir, 'python.exe'))
00779 
00780     # Extract the version from the configure file, needed to calculate
00781     # several paths.
00782     version = getVersion()
00783 
00784     # Since the extra libs are not in their installed framework location
00785     # during the build, augment the library path so that the interpreter
00786     # will find them during its extension import sanity checks.
00787     os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR,
00788                                         'libraries', 'usr', 'local', 'lib')
00789     print "Running configure..."
00790     runCommand("%s -C --enable-framework --enable-universalsdk=%s "
00791                "--with-universal-archs=%s "
00792                "%s "
00793                "LDFLAGS='-g -L%s/libraries/usr/local/lib' "
00794                "OPT='-g -O3 -I%s/libraries/usr/local/include' 2>&1"%(
00795         shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH),
00796         UNIVERSALARCHS,
00797         (' ', '--with-computed-gotos ')[PYTHON_3],
00798         shellQuote(WORKDIR)[1:-1],
00799         shellQuote(WORKDIR)[1:-1]))
00800 
00801     print "Running make"
00802     runCommand("make")
00803 
00804     print "Running make install"
00805     runCommand("make install DESTDIR=%s"%(
00806         shellQuote(rootDir)))
00807 
00808     print "Running make frameworkinstallextras"
00809     runCommand("make frameworkinstallextras DESTDIR=%s"%(
00810         shellQuote(rootDir)))
00811 
00812     del os.environ['DYLD_LIBRARY_PATH']
00813     print "Copying required shared libraries"
00814     if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')):
00815         runCommand("mv %s/* %s"%(
00816             shellQuote(os.path.join(
00817                 WORKDIR, 'libraries', 'Library', 'Frameworks',
00818                 'Python.framework', 'Versions', getVersion(),
00819                 'lib')),
00820             shellQuote(os.path.join(WORKDIR, '_root', 'Library', 'Frameworks',
00821                 'Python.framework', 'Versions', getVersion(),
00822                 'lib'))))
00823 
00824     print "Fix file modes"
00825     frmDir = os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework')
00826     gid = grp.getgrnam('admin').gr_gid
00827 
00828     for dirpath, dirnames, filenames in os.walk(frmDir):
00829         for dn in dirnames:
00830             os.chmod(os.path.join(dirpath, dn), 0775)
00831             os.chown(os.path.join(dirpath, dn), -1, gid)
00832 
00833 
00834         for fn in filenames:
00835             if os.path.islink(fn):
00836                 continue
00837 
00838             # "chmod g+w $fn"
00839             p = os.path.join(dirpath, fn)
00840             st = os.stat(p)
00841             os.chmod(p, stat.S_IMODE(st.st_mode) | stat.S_IWGRP)
00842             os.chown(p, -1, gid)
00843 
00844     if PYTHON_3:
00845         LDVERSION=None
00846         VERSION=None
00847         ABIFLAGS=None
00848 
00849         fp = open(os.path.join(buildDir, 'Makefile'), 'r')
00850         for ln in fp:
00851             if ln.startswith('VERSION='):
00852                 VERSION=ln.split()[1]
00853             if ln.startswith('ABIFLAGS='):
00854                 ABIFLAGS=ln.split()[1]
00855             if ln.startswith('LDVERSION='):
00856                 LDVERSION=ln.split()[1]
00857         fp.close()
00858 
00859         LDVERSION = LDVERSION.replace('$(VERSION)', VERSION)
00860         LDVERSION = LDVERSION.replace('$(ABIFLAGS)', ABIFLAGS)
00861         config_suffix = '-' + LDVERSION
00862     else:
00863         config_suffix = ''      # Python 2.x
00864 
00865     # We added some directories to the search path during the configure
00866     # phase. Remove those because those directories won't be there on
00867     # the end-users system.
00868     path =os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework',
00869                 'Versions', version, 'lib', 'python%s'%(version,),
00870                 'config' + config_suffix, 'Makefile')
00871     fp = open(path, 'r')
00872     data = fp.read()
00873     fp.close()
00874 
00875     data = data.replace('-L%s/libraries/usr/local/lib'%(WORKDIR,), '')
00876     data = data.replace('-I%s/libraries/usr/local/include'%(WORKDIR,), '')
00877     fp = open(path, 'w')
00878     fp.write(data)
00879     fp.close()
00880 
00881     # Add symlinks in /usr/local/bin, using relative links
00882     usr_local_bin = os.path.join(rootDir, 'usr', 'local', 'bin')
00883     to_framework = os.path.join('..', '..', '..', 'Library', 'Frameworks',
00884             'Python.framework', 'Versions', version, 'bin')
00885     if os.path.exists(usr_local_bin):
00886         shutil.rmtree(usr_local_bin)
00887     os.makedirs(usr_local_bin)
00888     for fn in os.listdir(
00889                 os.path.join(frmDir, 'Versions', version, 'bin')):
00890         os.symlink(os.path.join(to_framework, fn),
00891                    os.path.join(usr_local_bin, fn))
00892 
00893     os.chdir(curdir)
00894 
00895     if PYTHON_3:
00896         # Remove the 'Current' link, that way we don't accidently mess
00897         # with an already installed version of python 2
00898         os.unlink(os.path.join(rootDir, 'Library', 'Frameworks',
00899                             'Python.framework', 'Versions', 'Current'))

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.buildPythonDocs ( )

Definition at line 742 of file build-installer.py.

00742 
00743 def buildPythonDocs():
00744     # This stores the documentation as Resources/English.lproj/Documentation
00745     # inside the framwork. pydoc and IDLE will pick it up there.
00746     print "Install python documentation"
00747     rootDir = os.path.join(WORKDIR, '_root')
00748     buildDir = os.path.join('../../Doc')
00749     docdir = os.path.join(rootDir, 'pydocs')
00750     curDir = os.getcwd()
00751     os.chdir(buildDir)
00752     runCommand('make update')
00753     runCommand("make html PYTHON='%s'" % os.path.abspath(sys.executable))
00754     os.chdir(curDir)
00755     if not os.path.exists(docdir):
00756         os.mkdir(docdir)
00757     os.rename(os.path.join(buildDir, 'build', 'html'), docdir)
00758 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.buildRecipe (   recipe,
  basedir,
  archList 
)
Build software using a recipe. This function does the
'configure;make;make install' dance for C software, with a possibility
to customize this process, basically a poor-mans DarwinPorts.

Definition at line 618 of file build-installer.py.

00618 
00619 def buildRecipe(recipe, basedir, archList):
00620     """
00621     Build software using a recipe. This function does the
00622     'configure;make;make install' dance for C software, with a possibility
00623     to customize this process, basically a poor-mans DarwinPorts.
00624     """
00625     curdir = os.getcwd()
00626 
00627     name = recipe['name']
00628     url = recipe['url']
00629     configure = recipe.get('configure', './configure')
00630     install = recipe.get('install', 'make && make install DESTDIR=%s'%(
00631         shellQuote(basedir)))
00632 
00633     archiveName = os.path.split(url)[-1]
00634     sourceArchive = os.path.join(DEPSRC, archiveName)
00635 
00636     if not os.path.exists(DEPSRC):
00637         os.mkdir(DEPSRC)
00638 
00639 
00640     if os.path.exists(sourceArchive):
00641         print "Using local copy of %s"%(name,)
00642 
00643     else:
00644         print "Did not find local copy of %s"%(name,)
00645         print "Downloading %s"%(name,)
00646         downloadURL(url, sourceArchive)
00647         print "Archive for %s stored as %s"%(name, sourceArchive)
00648 
00649     print "Extracting archive for %s"%(name,)
00650     buildDir=os.path.join(WORKDIR, '_bld')
00651     if not os.path.exists(buildDir):
00652         os.mkdir(buildDir)
00653 
00654     workDir = extractArchive(buildDir, sourceArchive)
00655     os.chdir(workDir)
00656     if 'buildDir' in recipe:
00657         os.chdir(recipe['buildDir'])
00658 
00659 
00660     for fn in recipe.get('patches', ()):
00661         if fn.startswith('http://'):
00662             # Download the patch before applying it.
00663             path = os.path.join(DEPSRC, os.path.basename(fn))
00664             downloadURL(fn, path)
00665             fn = path
00666 
00667         fn = os.path.join(curdir, fn)
00668         runCommand('patch -p%s < %s'%(recipe.get('patchlevel', 1),
00669             shellQuote(fn),))
00670 
00671     if configure is not None:
00672         configure_args = [
00673             "--prefix=/usr/local",
00674             "--enable-static",
00675             "--disable-shared",
00676             #"CPP=gcc -arch %s -E"%(' -arch '.join(archList,),),
00677         ]
00678 
00679         if 'configure_pre' in recipe:
00680             args = list(recipe['configure_pre'])
00681             if '--disable-static' in args:
00682                 configure_args.remove('--enable-static')
00683             if '--enable-shared' in args:
00684                 configure_args.remove('--disable-shared')
00685             configure_args.extend(args)
00686 
00687         if recipe.get('useLDFlags', 1):
00688             configure_args.extend([
00689                 "CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
00690                         ' -arch '.join(archList),
00691                         shellQuote(SDKPATH)[1:-1],
00692                         shellQuote(basedir)[1:-1],),
00693                 "LDFLAGS=-syslibroot,%s -L%s/usr/local/lib -arch %s"%(
00694                     shellQuote(SDKPATH)[1:-1],
00695                     shellQuote(basedir)[1:-1],
00696                     ' -arch '.join(archList)),
00697             ])
00698         else:
00699             configure_args.extend([
00700                 "CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
00701                         ' -arch '.join(archList),
00702                         shellQuote(SDKPATH)[1:-1],
00703                         shellQuote(basedir)[1:-1],),
00704             ])
00705 
00706         if 'configure_post' in recipe:
00707             configure_args = configure_args = list(recipe['configure_post'])
00708 
00709         configure_args.insert(0, configure)
00710         configure_args = [ shellQuote(a) for a in configure_args ]
00711 
00712         if 'configure_env' in recipe:
00713             configure_args.insert(0, recipe['configure_env'])
00714 
00715         print "Running configure for %s"%(name,)
00716         runCommand(' '.join(configure_args) + ' 2>&1')
00717 
00718     print "Running install for %s"%(name,)
00719     runCommand('{ ' + install + ' ;} 2>&1')
00720 
00721     print "Done %s"%(name,)
00722     print ""
00723 
00724     os.chdir(curdir)

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.captureCommand (   commandline)

Definition at line 378 of file build-installer.py.

00378 
00379 def captureCommand(commandline):
00380     fd = os.popen(commandline, 'r')
00381     data = fd.read()
00382     xit = fd.close()
00383     if xit is not None:
00384         sys.stdout.write(data)
00385         raise RuntimeError, "command failed: %s"%(commandline,)
00386 
00387     return data

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.checkEnvironment ( )
Check that we're running on a supported system.

Definition at line 405 of file build-installer.py.

00405 
00406 def checkEnvironment():
00407     """
00408     Check that we're running on a supported system.
00409     """
00410 
00411     if sys.version_info[0:2] < (2, 4):
00412         fatal("This script must be run with Python 2.4 or later")
00413 
00414     if platform.system() != 'Darwin':
00415         fatal("This script should be run on a Mac OS X 10.4 (or later) system")
00416 
00417     if int(platform.release().split('.')[0]) < 8:
00418         fatal("This script should be run on a Mac OS X 10.4 (or later) system")
00419 
00420     if not os.path.exists(SDKPATH):
00421         fatal("Please install the latest version of Xcode and the %s SDK"%(
00422             os.path.basename(SDKPATH[:-4])))
00423 
00424     # Because we only support dynamic load of only one major/minor version of
00425     # Tcl/Tk, ensure:
00426     # 1. there are no user-installed frameworks of Tcl/Tk with version
00427     #       higher than the Apple-supplied system version
00428     # 2. there is a user-installed framework in /Library/Frameworks with the
00429     #       same version as the system version.  This allows users to choose
00430     #       to install a newer patch level.
00431 
00432     for framework in ['Tcl', 'Tk']:
00433         #fw = dict(lower=framework.lower(),
00434         #            upper=framework.upper(),
00435         #            cap=framework.capitalize())
00436         #fwpth = "Library/Frameworks/%(cap)s.framework/%(lower)sConfig.sh" % fw
00437         fwpth = 'Library/Frameworks/Tcl.framework/Versions/Current'
00438         sysfw = os.path.join(SDKPATH, 'System', fwpth)
00439         libfw = os.path.join('/', fwpth)
00440         usrfw = os.path.join(os.getenv('HOME'), fwpth)
00441         #version = "%(upper)s_VERSION" % fw
00442         if os.readlink(libfw) != os.readlink(sysfw):
00443             fatal("Version of %s must match %s" % (libfw, sysfw) )
00444         if os.path.exists(usrfw):
00445             fatal("Please rename %s to avoid possible dynamic load issues."
00446                     % usrfw)
00447 
00448     # Remove inherited environment variables which might influence build
00449     environ_var_prefixes = ['CPATH', 'C_INCLUDE_', 'DYLD_', 'LANG', 'LC_',
00450                             'LD_', 'LIBRARY_', 'PATH', 'PYTHON']
00451     for ev in list(os.environ):
00452         for prefix in environ_var_prefixes:
00453             if ev.startswith(prefix) :
00454                 print "INFO: deleting environment variable %s=%s" % (
00455                                                     ev, os.environ[ev])
00456                 del os.environ[ev]
00457 
00458     os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin'
00459     print "Setting default PATH: %s"%(os.environ['PATH'])
00460 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.downloadURL (   url,
  fname 
)
Download the contents of the url into the file.

Definition at line 591 of file build-installer.py.

00591 
00592 def downloadURL(url, fname):
00593     """
00594     Download the contents of the url into the file.
00595     """
00596     try:
00597         size = os.path.getsize(fname)
00598     except OSError:
00599         pass
00600     else:
00601         if KNOWNSIZES.get(url) == size:
00602             print "Using existing file for", url
00603             return
00604     fpIn = urllib2.urlopen(url)
00605     fpOut = open(fname, 'wb')
00606     block = fpIn.read(10240)
00607     try:
00608         while block:
00609             fpOut.write(block)
00610             block = fpIn.read(10240)
00611         fpIn.close()
00612         fpOut.close()
00613     except:
00614         try:
00615             os.unlink(fname)
00616         except:
00617             pass

Here is the caller graph for this function:

def build-installer.extractArchive (   builddir,
  archiveName 
)
Extract a source archive into 'builddir'. Returns the path of the
extracted archive.

XXX: This function assumes that archives contain a toplevel directory
that is has the same name as the basename of the archive. This is
save enough for anything we use.

Definition at line 539 of file build-installer.py.

00539 
00540 def extractArchive(builddir, archiveName):
00541     """
00542     Extract a source archive into 'builddir'. Returns the path of the
00543     extracted archive.
00544 
00545     XXX: This function assumes that archives contain a toplevel directory
00546     that is has the same name as the basename of the archive. This is
00547     save enough for anything we use.
00548     """
00549     curdir = os.getcwd()
00550     try:
00551         os.chdir(builddir)
00552         if archiveName.endswith('.tar.gz'):
00553             retval = os.path.basename(archiveName[:-7])
00554             if os.path.exists(retval):
00555                 shutil.rmtree(retval)
00556             fp = os.popen("tar zxf %s 2>&1"%(shellQuote(archiveName),), 'r')
00557 
00558         elif archiveName.endswith('.tar.bz2'):
00559             retval = os.path.basename(archiveName[:-8])
00560             if os.path.exists(retval):
00561                 shutil.rmtree(retval)
00562             fp = os.popen("tar jxf %s 2>&1"%(shellQuote(archiveName),), 'r')
00563 
00564         elif archiveName.endswith('.tar'):
00565             retval = os.path.basename(archiveName[:-4])
00566             if os.path.exists(retval):
00567                 shutil.rmtree(retval)
00568             fp = os.popen("tar xf %s 2>&1"%(shellQuote(archiveName),), 'r')
00569 
00570         elif archiveName.endswith('.zip'):
00571             retval = os.path.basename(archiveName[:-4])
00572             if os.path.exists(retval):
00573                 shutil.rmtree(retval)
00574             fp = os.popen("unzip %s 2>&1"%(shellQuote(archiveName),), 'r')
00575 
00576         data = fp.read()
00577         xit = fp.close()
00578         if xit is not None:
00579             sys.stdout.write(data)
00580             raise RuntimeError, "Cannot extract %s"%(archiveName,)
00581 
00582         return os.path.join(builddir, retval)
00583 
00584     finally:
00585         os.chdir(curdir)

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.fatal (   msg)
A fatal error, bail out.

Definition at line 348 of file build-installer.py.

00348 
00349 def fatal(msg):
00350     """
00351     A fatal error, bail out.
00352     """
00353     sys.stderr.write('FATAL: ')
00354     sys.stderr.write(msg)
00355     sys.stderr.write('\n')
00356     sys.exit(1)

Here is the caller graph for this function:

def build-installer.fileContents (   fn)
Return the contents of the named file

Definition at line 357 of file build-installer.py.

00357 
00358 def fileContents(fn):
00359     """
00360     Return the contents of the named file
00361     """
00362     return open(fn, 'rb').read()

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.getFullVersion ( )

Definition at line 53 of file build-installer.py.

00053 
00054 def getFullVersion():
00055     fn = os.path.join(SRCDIR, 'Include', 'patchlevel.h')
00056     for ln in open(fn):
00057         if 'PY_VERSION' in ln:
00058             return ln.split()[-1][1:-1]
00059     raise RuntimeError, "Cannot find full version??"
00060 
# The directory we'll use to create the build (will be erased and recreated)

Here is the caller graph for this function:

def build-installer.getTclTkVersion (   configfile,
  versionline 
)
search Tcl or Tk configuration file for version line

Definition at line 388 of file build-installer.py.

00388 
00389 def getTclTkVersion(configfile, versionline):
00390     """
00391     search Tcl or Tk configuration file for version line
00392     """
00393     try:
00394         f = open(configfile, "r")
00395     except:
00396         fatal("Framework configuration file not found: %s" % configfile)
00397 
00398     for l in f:
00399         if l.startswith(versionline):
00400             f.close()
00401             return l
00402 
00403     fatal("Version variable %s not found in framework configuration file: %s"
00404             % (versionline, configfile))

Here is the call graph for this function:

def build-installer.getVersion ( )

Definition at line 47 of file build-installer.py.

00047 
00048 def getVersion():
00049     return grepValue(os.path.join(SRCDIR, 'configure'), 'PACKAGE_VERSION')

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.getVersionTuple ( )

Definition at line 50 of file build-installer.py.

00050 
00051 def getVersionTuple():
00052     return tuple([int(n) for n in getVersion().split('.')])

Here is the call graph for this function:

def build-installer.grepValue (   fn,
  variable 
)

Definition at line 39 of file build-installer.py.

00039 
00040 def grepValue(fn, variable):
00041     variable = variable + '='
00042     for ln in open(fn, 'r'):
00043         if ln.startswith(variable):
00044             value = ln[len(variable):].strip()
00045             return value[1:-1]
00046     raise RuntimeError, "Cannot find variable %s" % variable[:-1]

Here is the caller graph for this function:

def build-installer.installSize (   clear = False,
  _saved = [] 
)

Definition at line 1090 of file build-installer.py.

01090 
01091 def installSize(clear=False, _saved=[]):
01092     if clear:
01093         del _saved[:]
01094     if not _saved:
01095         data = captureCommand("du -ks %s"%(
01096                     shellQuote(os.path.join(WORKDIR, '_root'))))
01097         _saved.append("%d"%((0.5 + (int(data.split()[0]) / 1024.0)),))
01098     return _saved[0]
01099 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.library_recipes ( )

Definition at line 143 of file build-installer.py.

00143 
00144 def library_recipes():
00145     result = []
00146 
00147     if DEPTARGET < '10.5':
00148         result.extend([
00149           dict(
00150               name="Bzip2 1.0.6",
00151               url="http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz",
00152               checksum='00b516f4704d4a7cb50a1d97e6e8e15b',
00153               configure=None,
00154               install='make install CC=%s PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
00155                   CC,
00156                   shellQuote(os.path.join(WORKDIR, 'libraries')),
00157                   ' -arch '.join(ARCHLIST),
00158                   SDKPATH,
00159               ),
00160           ),
00161           dict(
00162               name="ZLib 1.2.3",
00163               url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
00164               checksum='debc62758716a169df9f62e6ab2bc634',
00165               configure=None,
00166               install='make install CC=%s prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
00167                   CC,
00168                   shellQuote(os.path.join(WORKDIR, 'libraries')),
00169                   ' -arch '.join(ARCHLIST),
00170                   SDKPATH,
00171               ),
00172           ),
00173           dict(
00174               # Note that GNU readline is GPL'd software
00175               name="GNU Readline 6.1.2",
00176               url="http://ftp.gnu.org/pub/gnu/readline/readline-6.1.tar.gz" ,
00177               checksum='fc2f7e714fe792db1ce6ddc4c9fb4ef3',
00178               patchlevel='0',
00179               patches=[
00180                   # The readline maintainers don't do actual micro releases, but
00181                   # just ship a set of patches.
00182                   'http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-001',
00183                   'http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002',
00184               ]
00185           ),
00186           dict(
00187               name="SQLite 3.7.4",
00188               url="http://www.sqlite.org/sqlite-autoconf-3070400.tar.gz",
00189               checksum='8f0c690bfb33c3cbbc2471c3d9ba0158',
00190               configure_env=('CFLAGS="-Os'
00191                                   ' -DSQLITE_ENABLE_FTS3'
00192                                   ' -DSQLITE_ENABLE_FTS3_PARENTHESIS'
00193                                   ' -DSQLITE_ENABLE_RTREE'
00194                                   ' -DSQLITE_TCL=0'
00195                                   '"'),
00196               configure_pre=[
00197                   '--enable-threadsafe',
00198                   '--enable-shared=no',
00199                   '--enable-static=yes',
00200                   '--disable-readline',
00201                   '--disable-dependency-tracking',
00202               ]
00203           ),
00204           dict(
00205               name="NCurses 5.5",
00206               url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
00207               checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
00208               configure_pre=[
00209                   "--enable-widec",
00210                   "--without-cxx",
00211                   "--without-ada",
00212                   "--without-progs",
00213                   "--without-curses-h",
00214                   "--enable-shared",
00215                   "--with-shared",
00216                   "--datadir=/usr/share",
00217                   "--sysconfdir=/etc",
00218                   "--sharedstatedir=/usr/com",
00219                   "--with-terminfo-dirs=/usr/share/terminfo",
00220                   "--with-default-terminfo-dir=/usr/share/terminfo",
00221                   "--libdir=/Library/Frameworks/Python.framework/Versions/%s/lib"%(getVersion(),),
00222                   "--enable-termcap",
00223               ],
00224               patches=[
00225                   "ncurses-5.5.patch",
00226               ],
00227               useLDFlags=False,
00228               install='make && make install DESTDIR=%s && cd %s/usr/local/lib && ln -fs ../../../Library/Frameworks/Python.framework/Versions/%s/lib/lib* .'%(
00229                   shellQuote(os.path.join(WORKDIR, 'libraries')),
00230                   shellQuote(os.path.join(WORKDIR, 'libraries')),
00231                   getVersion(),
00232                   ),
00233           ),
00234         ])
00235 
00236     if not PYTHON_3:
00237         result.extend([
00238           dict(
00239               name="Sleepycat DB 4.7.25",
00240               url="http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz",
00241               checksum='ec2b87e833779681a0c3a814aa71359e',
00242               buildDir="build_unix",
00243               configure="../dist/configure",
00244               configure_pre=[
00245                   '--includedir=/usr/local/include/db4',
00246               ]
00247           ),
00248         ])
00249 
00250     return result
00251 
00252 
# Instructions for building packages inside the .mpkg.

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.main ( void  )

Definition at line 1164 of file build-installer.py.

01164 
01165 def main():
01166     # First parse options and check if we can perform our work
01167     parseOptions()
01168     checkEnvironment()
01169 
01170     os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET
01171     os.environ['CC'] = CC
01172 
01173     if os.path.exists(WORKDIR):
01174         shutil.rmtree(WORKDIR)
01175     os.mkdir(WORKDIR)
01176 
01177     os.environ['LC_ALL'] = 'C'
01178 
01179     # Then build third-party libraries such as sleepycat DB4.
01180     buildLibraries()
01181 
01182     # Now build python itself
01183     buildPython()
01184 
01185     # And then build the documentation
01186     # Remove the Deployment Target from the shell
01187     # environment, it's no longer needed and
01188     # an unexpected build target can cause problems
01189     # when Sphinx and its dependencies need to
01190     # be (re-)installed.
01191     del os.environ['MACOSX_DEPLOYMENT_TARGET']
01192     buildPythonDocs()
01193 
01194 
01195     # Prepare the applications folder
01196     fn = os.path.join(WORKDIR, "_root", "Applications",
01197                 "Python %s"%(getVersion(),), "Update Shell Profile.command")
01198     patchScript("scripts/postflight.patch-profile",  fn)
01199 
01200     folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(
01201         getVersion(),))
01202     os.chmod(folder, 0755)
01203     setIcon(folder, "../Icons/Python Folder.icns")
01204 
01205     # Create the installer
01206     buildInstaller()
01207 
01208     # And copy the readme into the directory containing the installer
01209     patchFile('resources/ReadMe.txt', os.path.join(WORKDIR, 'installer', 'ReadMe.txt'))
01210 
01211     # Ditto for the license file.
01212     shutil.copy('../../LICENSE', os.path.join(WORKDIR, 'installer', 'License.txt'))
01213 
01214     fp = open(os.path.join(WORKDIR, 'installer', 'Build.txt'), 'w')
01215     print >> fp, "# BUILD INFO"
01216     print >> fp, "# Date:", time.ctime()
01217     print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos
01218     fp.close()
01219 
01220     # And copy it to a DMG
01221     buildDMG()

Here is the call graph for this function:

def build-installer.makeMpkgPlist (   path)

Definition at line 1016 of file build-installer.py.

01016 
01017 def makeMpkgPlist(path):
01018 
01019     vers = getFullVersion()
01020     major, minor = map(int, getVersion().split('.', 2))
01021 
01022     pl = Plist(
01023             CFBundleGetInfoString="Python %s"%(vers,),
01024             CFBundleIdentifier='org.python.Python',
01025             CFBundleName='Python',
01026             CFBundleShortVersionString=vers,
01027             IFMajorVersion=major,
01028             IFMinorVersion=minor,
01029             IFPkgFlagComponentDirectory="Contents/Packages",
01030             IFPkgFlagPackageList=[
01031                 dict(
01032                     IFPkgFlagPackageLocation='%s-%s.pkg'%(item['name'], getVersion()),
01033                     IFPkgFlagPackageSelection=item.get('selected', 'selected'),
01034                 )
01035                 for item in pkg_recipes()
01036             ],
01037             IFPkgFormatVersion=0.10000000149011612,
01038             IFPkgFlagBackgroundScaling="proportional",
01039             IFPkgFlagBackgroundAlignment="left",
01040             IFPkgFlagAuthorizationAction="RootAuthorization",
01041         )
01042 
01043     writePlist(pl, path)
01044 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.packageFromRecipe (   targetDir,
  recipe 
)

Definition at line 924 of file build-installer.py.

00924 
00925 def packageFromRecipe(targetDir, recipe):
00926     curdir = os.getcwd()
00927     try:
00928         # The major version (such as 2.5) is included in the package name
00929         # because having two version of python installed at the same time is
00930         # common.
00931         pkgname = '%s-%s'%(recipe['name'], getVersion())
00932         srcdir  = recipe.get('source')
00933         pkgroot = recipe.get('topdir', srcdir)
00934         postflight = recipe.get('postflight')
00935         readme = textwrap.dedent(recipe['readme'])
00936         isRequired = recipe.get('required', True)
00937 
00938         print "- building package %s"%(pkgname,)
00939 
00940         # Substitute some variables
00941         textvars = dict(
00942             VER=getVersion(),
00943             FULLVER=getFullVersion(),
00944         )
00945         readme = readme % textvars
00946 
00947         if pkgroot is not None:
00948             pkgroot = pkgroot % textvars
00949         else:
00950             pkgroot = '/'
00951 
00952         if srcdir is not None:
00953             srcdir = os.path.join(WORKDIR, '_root', srcdir[1:])
00954             srcdir = srcdir % textvars
00955 
00956         if postflight is not None:
00957             postflight = os.path.abspath(postflight)
00958 
00959         packageContents = os.path.join(targetDir, pkgname + '.pkg', 'Contents')
00960         os.makedirs(packageContents)
00961 
00962         if srcdir is not None:
00963             os.chdir(srcdir)
00964             runCommand("pax -wf %s . 2>&1"%(shellQuote(os.path.join(packageContents, 'Archive.pax')),))
00965             runCommand("gzip -9 %s 2>&1"%(shellQuote(os.path.join(packageContents, 'Archive.pax')),))
00966             runCommand("mkbom . %s 2>&1"%(shellQuote(os.path.join(packageContents, 'Archive.bom')),))
00967 
00968         fn = os.path.join(packageContents, 'PkgInfo')
00969         fp = open(fn, 'w')
00970         fp.write('pmkrpkg1')
00971         fp.close()
00972 
00973         rsrcDir = os.path.join(packageContents, "Resources")
00974         os.mkdir(rsrcDir)
00975         fp = open(os.path.join(rsrcDir, 'ReadMe.txt'), 'w')
00976         fp.write(readme)
00977         fp.close()
00978 
00979         if postflight is not None:
00980             patchScript(postflight, os.path.join(rsrcDir, 'postflight'))
00981 
00982         vers = getFullVersion()
00983         major, minor = map(int, getVersion().split('.', 2))
00984         pl = Plist(
00985                 CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,),
00986                 CFBundleIdentifier='org.python.Python.%s'%(pkgname,),
00987                 CFBundleName='Python.%s'%(pkgname,),
00988                 CFBundleShortVersionString=vers,
00989                 IFMajorVersion=major,
00990                 IFMinorVersion=minor,
00991                 IFPkgFormatVersion=0.10000000149011612,
00992                 IFPkgFlagAllowBackRev=False,
00993                 IFPkgFlagAuthorizationAction="RootAuthorization",
00994                 IFPkgFlagDefaultLocation=pkgroot,
00995                 IFPkgFlagFollowLinks=True,
00996                 IFPkgFlagInstallFat=True,
00997                 IFPkgFlagIsRequired=isRequired,
00998                 IFPkgFlagOverwritePermissions=False,
00999                 IFPkgFlagRelocatable=False,
01000                 IFPkgFlagRestartAction="NoRestart",
01001                 IFPkgFlagRootVolumeOnly=True,
01002                 IFPkgFlagUpdateInstalledLangauges=False,
01003             )
01004         writePlist(pl, os.path.join(packageContents, 'Info.plist'))
01005 
01006         pl = Plist(
01007                     IFPkgDescriptionDescription=readme,
01008                     IFPkgDescriptionTitle=recipe.get('long_name', "Python.%s"%(pkgname,)),
01009                     IFPkgDescriptionVersion=vers,
01010                 )
01011         writePlist(pl, os.path.join(packageContents, 'Resources', 'Description.plist'))
01012 
01013     finally:
01014         os.chdir(curdir)
01015 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.parseOptions (   args = None)
Parse arguments and update global settings.

Definition at line 461 of file build-installer.py.

00461 
00462 def parseOptions(args=None):
00463     """
00464     Parse arguments and update global settings.
00465     """
00466     global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET
00467     global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC
00468 
00469     if args is None:
00470         args = sys.argv[1:]
00471 
00472     try:
00473         options, args = getopt.getopt(args, '?hb',
00474                 [ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=',
00475                   'dep-target=', 'universal-archs=', 'help' ])
00476     except getopt.error, msg:
00477         print msg
00478         sys.exit(1)
00479 
00480     if args:
00481         print "Additional arguments"
00482         sys.exit(1)
00483 
00484     deptarget = None
00485     for k, v in options:
00486         if k in ('-h', '-?', '--help'):
00487             print USAGE
00488             sys.exit(0)
00489 
00490         elif k in ('-d', '--build-dir'):
00491             WORKDIR=v
00492 
00493         elif k in ('--third-party',):
00494             DEPSRC=v
00495 
00496         elif k in ('--sdk-path',):
00497             SDKPATH=v
00498 
00499         elif k in ('--src-dir',):
00500             SRCDIR=v
00501 
00502         elif k in ('--dep-target', ):
00503             DEPTARGET=v
00504             deptarget=v
00505 
00506         elif k in ('--universal-archs', ):
00507             if v in UNIVERSALOPTS:
00508                 UNIVERSALARCHS = v
00509                 ARCHLIST = universal_opts_map[UNIVERSALARCHS]
00510                 if deptarget is None:
00511                     # Select alternate default deployment
00512                     # target
00513                     DEPTARGET = default_target_map.get(v, '10.3')
00514             else:
00515                 raise NotImplementedError, v
00516 
00517         else:
00518             raise NotImplementedError, k
00519 
00520     SRCDIR=os.path.abspath(SRCDIR)
00521     WORKDIR=os.path.abspath(WORKDIR)
00522     SDKPATH=os.path.abspath(SDKPATH)
00523     DEPSRC=os.path.abspath(DEPSRC)
00524 
00525     CC=target_cc_map[DEPTARGET]
00526 
00527     print "Settings:"
00528     print " * Source directory:", SRCDIR
00529     print " * Build directory: ", WORKDIR
00530     print " * SDK location:    ", SDKPATH
00531     print " * Third-party source:", DEPSRC
00532     print " * Deployment target:", DEPTARGET
00533     print " * Universal architectures:", ARCHLIST
00534     print " * C compiler:", CC
00535     print ""
00536 
00537 
00538 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.patchFile (   inPath,
  outPath 
)

Definition at line 900 of file build-installer.py.

00900 
00901 def patchFile(inPath, outPath):
00902     data = fileContents(inPath)
00903     data = data.replace('$FULL_VERSION', getFullVersion())
00904     data = data.replace('$VERSION', getVersion())
00905     data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later')))
00906     data = data.replace('$ARCHITECTURES', ", ".join(universal_opts_map[UNIVERSALARCHS]))
00907     data = data.replace('$INSTALL_SIZE', installSize())
00908 
00909     # This one is not handy as a template variable
00910     data = data.replace('$PYTHONFRAMEWORKINSTALLDIR', '/Library/Frameworks/Python.framework')
00911     fp = open(outPath, 'wb')
00912     fp.write(data)
00913     fp.close()

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.patchScript (   inPath,
  outPath 
)

Definition at line 914 of file build-installer.py.

00914 
00915 def patchScript(inPath, outPath):
00916     data = fileContents(inPath)
00917     data = data.replace('@PYVER@', getVersion())
00918     fp = open(outPath, 'wb')
00919     fp.write(data)
00920     fp.close()
00921     os.chmod(outPath, 0755)
00922 
00923 

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.pkg_recipes ( )

Definition at line 253 of file build-installer.py.

00253 
00254 def pkg_recipes():
00255     unselected_for_python3 = ('selected', 'unselected')[PYTHON_3]
00256     result = [
00257         dict(
00258             name="PythonFramework",
00259             long_name="Python Framework",
00260             source="/Library/Frameworks/Python.framework",
00261             readme="""\
00262                 This package installs Python.framework, that is the python
00263                 interpreter and the standard library. This also includes Python
00264                 wrappers for lots of Mac OS X API's.
00265             """,
00266             postflight="scripts/postflight.framework",
00267             selected='selected',
00268         ),
00269         dict(
00270             name="PythonApplications",
00271             long_name="GUI Applications",
00272             source="/Applications/Python %(VER)s",
00273             readme="""\
00274                 This package installs IDLE (an interactive Python IDE),
00275                 Python Launcher and Build Applet (create application bundles
00276                 from python scripts).
00277 
00278                 It also installs a number of examples and demos.
00279                 """,
00280             required=False,
00281             selected='selected',
00282         ),
00283         dict(
00284             name="PythonUnixTools",
00285             long_name="UNIX command-line tools",
00286             source="/usr/local/bin",
00287             readme="""\
00288                 This package installs the unix tools in /usr/local/bin for
00289                 compatibility with older releases of Python. This package
00290                 is not necessary to use Python.
00291                 """,
00292             required=False,
00293             selected='selected',
00294         ),
00295         dict(
00296             name="PythonDocumentation",
00297             long_name="Python Documentation",
00298             topdir="/Library/Frameworks/Python.framework/Versions/%(VER)s/Resources/English.lproj/Documentation",
00299             source="/pydocs",
00300             readme="""\
00301                 This package installs the python documentation at a location
00302                 that is useable for pydoc and IDLE. If you have installed Xcode
00303                 it will also install a link to the documentation in
00304                 /Developer/Documentation/Python
00305                 """,
00306             postflight="scripts/postflight.documentation",
00307             required=False,
00308             selected='selected',
00309         ),
00310         dict(
00311             name="PythonProfileChanges",
00312             long_name="Shell profile updater",
00313             readme="""\
00314                 This packages updates your shell profile to make sure that
00315                 the Python tools are found by your shell in preference of
00316                 the system provided Python tools.
00317 
00318                 If you don't install this package you'll have to add
00319                 "/Library/Frameworks/Python.framework/Versions/%(VER)s/bin"
00320                 to your PATH by hand.
00321                 """,
00322             postflight="scripts/postflight.patch-profile",
00323             topdir="/Library/Frameworks/Python.framework",
00324             source="/empty-dir",
00325             required=False,
00326             selected=unselected_for_python3,
00327         ),
00328     ]
00329 
00330     if DEPTARGET < '10.4':
00331         result.append(
00332             dict(
00333                 name="PythonSystemFixes",
00334                 long_name="Fix system Python",
00335                 readme="""\
00336                     This package updates the system python installation on
00337                     Mac OS X 10.3 to ensure that you can build new python extensions
00338                     using that copy of python after installing this version.
00339                     """,
00340                 postflight="../Tools/fixapplepython23.py",
00341                 topdir="/Library/Frameworks/Python.framework",
00342                 source="/empty-dir",
00343                 required=False,
00344                 selected=unselected_for_python3,
00345             )
00346         )
00347     return result

Here is the caller graph for this function:

def build-installer.runCommand (   commandline)
Run a command and raise RuntimeError if it fails. Output is suppressed
unless the command fails.

Definition at line 363 of file build-installer.py.

00363 
00364 def runCommand(commandline):
00365     """
00366     Run a command and raise RuntimeError if it fails. Output is suppressed
00367     unless the command fails.
00368     """
00369     fd = os.popen(commandline, 'r')
00370     data = fd.read()
00371     xit = fd.close()
00372     if xit is not None:
00373         sys.stdout.write(data)
00374         raise RuntimeError, "command failed: %s"%(commandline,)
00375 
00376     if VERBOSE:
00377         sys.stdout.write(data); sys.stdout.flush()

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.setIcon (   filePath,
  icnsPath 
)
Set the custom icon for the specified file or directory.

Definition at line 1145 of file build-installer.py.

01145 
01146 def setIcon(filePath, icnsPath):
01147     """
01148     Set the custom icon for the specified file or directory.
01149     """
01150 
01151     dirPath = os.path.normpath(os.path.dirname(__file__))
01152     toolPath = os.path.join(dirPath, "seticon.app/Contents/MacOS/seticon")
01153     if not os.path.exists(toolPath) or os.stat(toolPath).st_mtime < os.stat(dirPath + '/seticon.m').st_mtime:
01154         # NOTE: The tool is created inside an .app bundle, otherwise it won't work due
01155         # to connections to the window server.
01156         appPath = os.path.join(dirPath, "seticon.app/Contents/MacOS")
01157         if not os.path.exists(appPath):
01158             os.makedirs(appPath)
01159         runCommand("cc -o %s %s/seticon.m -framework Cocoa"%(
01160             shellQuote(toolPath), shellQuote(dirPath)))
01161 
01162     runCommand("%s %s %s"%(shellQuote(os.path.abspath(toolPath)), shellQuote(icnsPath),
01163         shellQuote(filePath)))

Here is the call graph for this function:

Here is the caller graph for this function:

def build-installer.shellQuote (   value)
Return the string value in a form that can safely be inserted into
a shell command.

Definition at line 32 of file build-installer.py.

00032 
00033 def shellQuote(value):
00034     """
00035     Return the string value in a form that can safely be inserted into
00036     a shell command.
00037     """
00038     return "'%s'"%(value.replace("'", "'\"'\"'"))

Here is the caller graph for this function:

def build-installer.writePlist (   plist,
  path 
)

Definition at line 29 of file build-installer.py.

00029 
00030     def writePlist(plist, path):
00031         plist.write(path)

Here is the caller graph for this function:


Variable Documentation

list build-installer.ARCHLIST = universal_opts_map[UNIVERSALARCHS]

Definition at line 101 of file build-installer.py.

list build-installer.CC = target_cc_map[DEPTARGET]

Definition at line 120 of file build-installer.py.

dictionary build-installer.default_target_map
Initial value:
00001 {
00002         '64-bit': '10.5',
00003         '3-way': '10.5',
00004         'intel': '10.5',
00005         'all': '10.5',
00006 }

Definition at line 90 of file build-installer.py.

tuple build-installer.DEPSRC = os.path.join(WORKDIR, 'third-party')

Definition at line 65 of file build-installer.py.

string build-installer.DEPTARGET = '10.3'

Definition at line 111 of file build-installer.py.

int build-installer.INCLUDE_TIMESTAMP = 1

Definition at line 18 of file build-installer.py.

dictionary build-installer.KNOWNSIZES
Initial value:
00001 {
00002     "http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz": 7952742,
00003     "http://downloads.sleepycat.com/db-4.4.20.tar.gz": 2030276,
00004 }

Definition at line 586 of file build-installer.py.

tuple build-installer.PYTHON_3 = getVersionTuple()

Definition at line 122 of file build-installer.py.

string build-installer.SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk"

There are some issues with the SDK selection below here, The resulting binary doesn't work on all platforms that it should.

Always default to the 10.4u SDK until that isue is resolved.

if int(os.uname()[2].split('.')[0]) == 8:

Explicitly use the 10.4u (universal) SDK when

building on 10.4, the system headers are not

useable for a universal build

SDKPATH = "/Developer/SDKs/MacOSX10.4u.sdk" else: SDKPATH = "/"

Definition at line 83 of file build-installer.py.

tuple build-installer.SRCDIR
Initial value:
00001 os.path.dirname(
00002         os.path.dirname(
00003             os.path.dirname(
00004                 os.path.abspath(__file__
00005         ))))

Definition at line 104 of file build-installer.py.

dictionary build-installer.target_cc_map
Initial value:
00001 {
00002         '10.3': 'gcc-4.0',
00003         '10.4': 'gcc-4.0',
00004         '10.5': 'gcc-4.0',
00005         '10.6': 'gcc-4.2',
00006 }

Definition at line 113 of file build-installer.py.

dictionary build-installer.universal_opts_map
Initial value:
00001 { '32-bit': ('i386', 'ppc',),
00002                        '64-bit': ('x86_64', 'ppc64',),
00003                        'intel':  ('i386', 'x86_64'),
00004                        '3-way':  ('ppc', 'i386', 'x86_64'),
00005                        'all':    ('i386', 'ppc', 'x86_64', 'ppc64',) }

Definition at line 85 of file build-installer.py.

string build-installer.UNIVERSALARCHS = '32-bit'

Definition at line 99 of file build-installer.py.

tuple build-installer.UNIVERSALOPTS = tuple(universal_opts_map.keys())

Definition at line 97 of file build-installer.py.

tuple build-installer.USAGE
Initial value:
00001 textwrap.dedent("""\
00002     Usage: build_python [options]    Options:    -? or -h:            Show this message    -b DIR    --build-dir=DIR:     Create build here (default: %(WORKDIR)r)    --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)""")

Definition at line 124 of file build-installer.py.

int build-installer.VERBOSE = 1

Definition at line 19 of file build-installer.py.

string build-installer.WORKDIR = "/tmp/_py"

Definition at line 61 of file build-installer.py.