summaryrefslogtreecommitdiffstats
path: root/Mac/BuildScript/build-installer.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mac/BuildScript/build-installer.py')
-rwxr-xr-xMac/BuildScript/build-installer.py391
1 files changed, 275 insertions, 116 deletions
diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py
index fd5d5c3..8728289 100755
--- a/Mac/BuildScript/build-installer.py
+++ b/Mac/BuildScript/build-installer.py
@@ -8,7 +8,9 @@ OS X 10.5 and the 10.5 SDK.
Please ensure that this script keeps working with Python 2.5, to avoid
bootstrap issues (/usr/bin/python is Python 2.5 on OSX 10.5). Sphinx,
which is used to build the documentation, currently requires at least
-Python 2.4.
+Python 2.4. However, as of Python 3.4.1, Doc builds require an external
+sphinx-build and the current versions of Sphinx now require at least
+Python 2.6.
In addition to what is supplied with OS X 10.5+ and Xcode 3+, the script
requires an installed version of hg and a third-party version of
@@ -21,8 +23,8 @@ installing the most recent ActiveTcl 8.4 or 8.5 version.
32-bit-only installer builds are still possible on OS X 10.4 with Xcode 2.5
and the installation of additional components, such as a newer Python
-(2.5 is needed for Python parser updates), hg, and svn (for the documentation
-build).
+(2.5 is needed for Python parser updates), hg, and for the documentation
+build either svn (pre-3.4.1) or sphinx-build (3.4.1 and later).
Usage: see USAGE variable in the script.
"""
@@ -60,11 +62,16 @@ def shellQuote(value):
return "'%s'"%(value.replace("'", "'\"'\"'"))
def grepValue(fn, variable):
+ """
+ Return the unquoted value of a variable from a file..
+ QUOTED_VALUE='quotes' -> str('quotes')
+ UNQUOTED_VALUE=noquotes -> str('noquotes')
+ """
variable = variable + '='
for ln in open(fn, 'r'):
if ln.startswith(variable):
value = ln[len(variable):].strip()
- return value[1:-1]
+ return value.strip("\"'")
raise RuntimeError("Cannot find variable %s" % variable[:-1])
_cache_getVersion = None
@@ -76,9 +83,6 @@ def getVersion():
os.path.join(SRCDIR, 'configure'), 'PACKAGE_VERSION')
return _cache_getVersion
-def getVersionTuple():
- return tuple([int(n) for n in getVersion().split('.')])
-
def getVersionMajorMinor():
return tuple([int(n) for n in getVersion().split('.', 2)])
@@ -95,6 +99,9 @@ def getFullVersion():
return _cache_getFullVersion
raise RuntimeError("Cannot find full version??")
+FW_PREFIX = ["Library", "Frameworks", "Python.framework"]
+FW_VERSION_PREFIX = "--undefined--" # initialized in parseOptions
+
# The directory we'll use to create the build (will be erased and recreated)
WORKDIR = "/tmp/_py"
@@ -148,19 +155,21 @@ SRCDIR = os.path.dirname(
# $MACOSX_DEPLOYMENT_TARGET -> minimum OS X level
DEPTARGET = '10.3'
-target_cc_map = {
+def getDeptargetTuple():
+ return tuple([int(n) for n in DEPTARGET.split('.')[0:2]])
+
+def getTargetCompilers():
+ target_cc_map = {
'10.3': ('gcc-4.0', 'g++-4.0'),
'10.4': ('gcc-4.0', 'g++-4.0'),
'10.5': ('gcc-4.2', 'g++-4.2'),
'10.6': ('gcc-4.2', 'g++-4.2'),
- '10.7': ('clang', 'clang++'),
- '10.8': ('clang', 'clang++'),
- '10.9': ('clang', 'clang++'),
-}
+ }
+ return target_cc_map.get(DEPTARGET, ('clang', 'clang++') )
-CC, CXX = target_cc_map[DEPTARGET]
+CC, CXX = getTargetCompilers()
-PYTHON_3 = getVersionTuple() >= (3, 0)
+PYTHON_3 = getVersionMajorMinor() >= (3, 0)
USAGE = textwrap.dedent("""\
Usage: build_python [options]
@@ -184,6 +193,10 @@ USAGE = textwrap.dedent("""\
# '/Library/Frameworks/Tk.framework/Versions/8.5/Tk']
EXPECTED_SHARED_LIBS = {}
+# List of names of third party software built with this installer.
+# The names will be inserted into the rtf version of the License.
+THIRD_PARTY_LIBS = []
+
# Instructions for building libraries that are necessary for building a
# batteries included python.
# [The recipes are defined here for convenience but instantiated later after
@@ -191,9 +204,53 @@ EXPECTED_SHARED_LIBS = {}
def library_recipes():
result = []
- LT_10_5 = bool(DEPTARGET < '10.5')
+ LT_10_5 = bool(getDeptargetTuple() < (10, 5))
+
+ if getDeptargetTuple() < (10, 6):
+ # The OpenSSL libs shipped with OS X 10.5 and earlier are
+ # hopelessly out-of-date and do not include Apple's tie-in to
+ # the root certificates in the user and system keychains via TEA
+ # that was introduced in OS X 10.6. Note that this applies to
+ # programs built and linked with a 10.5 SDK even when run on
+ # newer versions of OS X.
+ #
+ # Dealing with CAs is messy. For now, just supply a
+ # local libssl and libcrypto for the older installer variants
+ # (e.g. the python.org 10.5+ 32-bit-only installer) that use the
+ # same default ssl certfile location as the system libs do:
+ # /System/Library/OpenSSL/cert.pem
+ # Then at least TLS connections can be negotiated with sites that
+ # use sha-256 certs like python.org, assuming the proper CA certs
+ # have been supplied. The default CA cert management issues for
+ # 10.5 and earlier builds are the same as before, other than it is
+ # now more obvious with cert checking enabled by default in the
+ # standard library.
+ #
+ # For builds with 10.6+ SDKs, continue to use the deprecated but
+ # less out-of-date Apple 0.9.8 libs for now. While they are less
+ # secure than using an up-to-date 1.0.1 version, doing so
+ # avoids the big problems of forcing users to have to manage
+ # default CAs themselves, thanks to the Apple libs using private TEA
+ # APIs for cert validation from keychains if validation using the
+ # standard OpenSSL locations (/System/Library/OpenSSL, normally empty)
+ # fails.
+
+ result.extend([
+ dict(
+ name="OpenSSL 1.0.2a",
+ url="https://www.openssl.org/source/openssl-1.0.2a.tar.gz",
+ checksum='a06c547dac9044161a477211049f60ef',
+ patches=[
+ "openssl_sdk_makedepend.patch",
+ ],
+ buildrecipe=build_universal_openssl,
+ configure=None,
+ install=None,
+ ),
+ ])
- if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)):
+# Disable for now
+ if False: # if getDeptargetTuple() > (10, 5):
result.extend([
dict(
name="Tcl 8.5.15",
@@ -234,12 +291,12 @@ def library_recipes():
),
])
- if getVersionTuple() >= (3, 3):
+ if PYTHON_3:
result.extend([
dict(
- name="XZ 5.0.3",
- url="http://tukaani.org/xz/xz-5.0.3.tar.gz",
- checksum='fefe52f9ecd521de2a8ce38c21a27574',
+ name="XZ 5.0.5",
+ url="http://tukaani.org/xz/xz-5.0.5.tar.gz",
+ checksum='19d924e066b6fff0bc9d1981b4e53196',
configure_pre=[
'--disable-dependency-tracking',
]
@@ -282,9 +339,9 @@ def library_recipes():
),
),
dict(
- name="SQLite 3.7.13",
- url="http://www.sqlite.org/sqlite-autoconf-3071300.tar.gz",
- checksum='c97df403e8a3d5b67bb408fcd6aabd8e',
+ name="SQLite 3.8.3.1",
+ url="http://www.sqlite.org/2014/sqlite-autoconf-3080301.tar.gz",
+ checksum='509ff98d8dc9729b618b7e96612079c6',
extra_cflags=('-Os '
'-DSQLITE_ENABLE_FTS4 '
'-DSQLITE_ENABLE_FTS3_PARENTHESIS '
@@ -301,7 +358,7 @@ def library_recipes():
),
])
- if DEPTARGET < '10.5':
+ if getDeptargetTuple() < (10, 5):
result.extend([
dict(
name="Bzip2 1.0.6",
@@ -432,11 +489,24 @@ def pkg_recipes():
topdir="/Library/Frameworks/Python.framework",
source="/empty-dir",
required=False,
- selected=unselected_for_python3,
+ selected='selected',
+ ),
+ dict(
+ name="PythonInstallPip",
+ long_name="Install or upgrade pip",
+ readme="""\
+ This package installs (or upgrades from an earlier version)
+ pip, a tool for installing and managing Python packages.
+ """,
+ postflight="scripts/postflight.ensurepip",
+ topdir="/Library/Frameworks/Python.framework",
+ source="/empty-dir",
+ required=False,
+ selected='selected',
),
]
- if DEPTARGET < '10.4' and not PYTHON_3:
+ if getDeptargetTuple() < (10, 4) and not PYTHON_3:
result.append(
dict(
name="PythonSystemFixes",
@@ -453,6 +523,7 @@ def pkg_recipes():
selected=unselected_for_python3,
)
)
+
return result
def fatal(msg):
@@ -567,20 +638,6 @@ def checkEnvironment():
% frameworks['Tk'],
]
- # For 10.6+ builds, we build two versions of _tkinter:
- # - the traditional version (renamed to _tkinter_library.so) linked
- # with /Library/Frameworks/{Tcl,Tk}.framework
- # - the default version linked with our builtin copies of Tcl and Tk
- if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)):
- EXPECTED_SHARED_LIBS['_tkinter_library.so'] = \
- EXPECTED_SHARED_LIBS['_tkinter.so']
- EXPECTED_SHARED_LIBS['_tkinter.so'] = [
- "/Library/Frameworks/Python.framework/Versions/%s/lib/libtcl%s.dylib"
- % (getVersion(), frameworks['Tcl']),
- "/Library/Frameworks/Python.framework/Versions/%s/lib/libtk%s.dylib"
- % (getVersion(), frameworks['Tk']),
- ]
-
# Remove inherited environment variables which might influence build
environ_var_prefixes = ['CPATH', 'C_INCLUDE_', 'DYLD_', 'LANG', 'LC_',
'LD_', 'LIBRARY_', 'PATH', 'PYTHON']
@@ -601,7 +658,10 @@ def checkEnvironment():
base_path = base_path + ':' + OLD_DEVELOPER_TOOLS
os.environ['PATH'] = base_path
print("Setting default PATH: %s"%(os.environ['PATH']))
-
+ # Ensure ws have access to hg and to sphinx-build.
+ # You may have to create links in /usr/bin for them.
+ runCommand('hg --version')
+ runCommand('sphinx-build --version')
def parseOptions(args=None):
"""
@@ -609,6 +669,7 @@ def parseOptions(args=None):
"""
global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET
global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC, CXX
+ global FW_VERSION_PREFIX
if args is None:
args = sys.argv[1:]
@@ -666,21 +727,23 @@ def parseOptions(args=None):
SDKPATH=os.path.abspath(SDKPATH)
DEPSRC=os.path.abspath(DEPSRC)
- CC, CXX=target_cc_map[DEPTARGET]
-
- print("Settings:")
- print(" * Source directory:", SRCDIR)
- print(" * Build directory: ", WORKDIR)
- print(" * SDK location: ", SDKPATH)
- print(" * Third-party source:", DEPSRC)
- print(" * Deployment target:", DEPTARGET)
- print(" * Universal architectures:", ARCHLIST)
- print(" * C compiler:", CC)
- print(" * C++ compiler:", CXX)
- print("")
-
+ CC, CXX = getTargetCompilers()
+ FW_VERSION_PREFIX = FW_PREFIX[:] + ["Versions", getVersion()]
+ print("-- Settings:")
+ print(" * Source directory: %s" % SRCDIR)
+ print(" * Build directory: %s" % WORKDIR)
+ print(" * SDK location: %s" % SDKPATH)
+ print(" * Third-party source: %s" % DEPSRC)
+ print(" * Deployment target: %s" % DEPTARGET)
+ print(" * Universal archs: %s" % str(ARCHLIST))
+ print(" * C compiler: %s" % CC)
+ print(" * C++ compiler: %s" % CXX)
+ print("")
+ print(" -- Building a Python %s framework at patch level %s"
+ % (getVersion(), getFullVersion()))
+ print("")
def extractArchive(builddir, archiveName):
"""
@@ -772,6 +835,132 @@ def verifyThirdPartyFile(url, checksum, fname):
% (shellQuote(fname), checksum) ):
fatal('MD5 checksum mismatch for file %s' % fname)
+def build_universal_openssl(basedir, archList):
+ """
+ Special case build recipe for universal build of openssl.
+
+ The upstream OpenSSL build system does not directly support
+ OS X universal builds. We need to build each architecture
+ separately then lipo them together into fat libraries.
+ """
+
+ # OpenSSL fails to build with Xcode 2.5 (on OS X 10.4).
+ # If we are building on a 10.4.x or earlier system,
+ # unilaterally disable assembly code building to avoid the problem.
+ no_asm = int(platform.release().split(".")[0]) < 9
+
+ def build_openssl_arch(archbase, arch):
+ "Build one architecture of openssl"
+ arch_opts = {
+ "i386": ["darwin-i386-cc"],
+ "x86_64": ["darwin64-x86_64-cc", "enable-ec_nistp_64_gcc_128"],
+ "ppc": ["darwin-ppc-cc"],
+ "ppc64": ["darwin64-ppc-cc"],
+ }
+ configure_opts = [
+ "no-krb5",
+ "no-idea",
+ "no-mdc2",
+ "no-rc5",
+ "no-zlib",
+ "enable-tlsext",
+ "no-ssl2",
+ "no-ssl3",
+ "no-ssl3-method",
+ # "enable-unit-test",
+ "shared",
+ "--install_prefix=%s"%shellQuote(archbase),
+ "--prefix=%s"%os.path.join("/", *FW_VERSION_PREFIX),
+ "--openssldir=/System/Library/OpenSSL",
+ ]
+ if no_asm:
+ configure_opts.append("no-asm")
+ runCommand(" ".join(["perl", "Configure"]
+ + arch_opts[arch] + configure_opts))
+ runCommand("make depend OSX_SDK=%s" % SDKPATH)
+ runCommand("make all OSX_SDK=%s" % SDKPATH)
+ runCommand("make install_sw OSX_SDK=%s" % SDKPATH)
+ # runCommand("make test")
+ return
+
+ srcdir = os.getcwd()
+ universalbase = os.path.join(srcdir, "..",
+ os.path.basename(srcdir) + "-universal")
+ os.mkdir(universalbase)
+ archbasefws = []
+ for arch in archList:
+ # fresh copy of the source tree
+ archsrc = os.path.join(universalbase, arch, "src")
+ shutil.copytree(srcdir, archsrc, symlinks=True)
+ # install base for this arch
+ archbase = os.path.join(universalbase, arch, "root")
+ os.mkdir(archbase)
+ # Python framework base within install_prefix:
+ # the build will install into this framework..
+ # This is to ensure that the resulting shared libs have
+ # the desired real install paths built into them.
+ archbasefw = os.path.join(archbase, *FW_VERSION_PREFIX)
+
+ # build one architecture
+ os.chdir(archsrc)
+ build_openssl_arch(archbase, arch)
+ os.chdir(srcdir)
+ archbasefws.append(archbasefw)
+
+ # copy arch-independent files from last build into the basedir framework
+ basefw = os.path.join(basedir, *FW_VERSION_PREFIX)
+ shutil.copytree(
+ os.path.join(archbasefw, "include", "openssl"),
+ os.path.join(basefw, "include", "openssl")
+ )
+
+ shlib_version_number = grepValue(os.path.join(archsrc, "Makefile"),
+ "SHLIB_VERSION_NUMBER")
+ # e.g. -> "1.0.0"
+ libcrypto = "libcrypto.dylib"
+ libcrypto_versioned = libcrypto.replace(".", "."+shlib_version_number+".")
+ # e.g. -> "libcrypto.1.0.0.dylib"
+ libssl = "libssl.dylib"
+ libssl_versioned = libssl.replace(".", "."+shlib_version_number+".")
+ # e.g. -> "libssl.1.0.0.dylib"
+
+ try:
+ os.mkdir(os.path.join(basefw, "lib"))
+ except OSError:
+ pass
+
+ # merge the individual arch-dependent shared libs into a fat shared lib
+ archbasefws.insert(0, basefw)
+ for (lib_unversioned, lib_versioned) in [
+ (libcrypto, libcrypto_versioned),
+ (libssl, libssl_versioned)
+ ]:
+ runCommand("lipo -create -output " +
+ " ".join(shellQuote(
+ os.path.join(fw, "lib", lib_versioned))
+ for fw in archbasefws))
+ # and create an unversioned symlink of it
+ os.symlink(lib_versioned, os.path.join(basefw, "lib", lib_unversioned))
+
+ # Create links in the temp include and lib dirs that will be injected
+ # into the Python build so that setup.py can find them while building
+ # and the versioned links so that the setup.py post-build import test
+ # does not fail.
+ relative_path = os.path.join("..", "..", "..", *FW_VERSION_PREFIX)
+ for fn in [
+ ["include", "openssl"],
+ ["lib", libcrypto],
+ ["lib", libssl],
+ ["lib", libcrypto_versioned],
+ ["lib", libssl_versioned],
+ ]:
+ os.symlink(
+ os.path.join(relative_path, *fn),
+ os.path.join(basedir, "usr", "local", *fn)
+ )
+
+ return
+
def buildRecipe(recipe, basedir, archList):
"""
Build software using a recipe. This function does the
@@ -781,8 +970,10 @@ def buildRecipe(recipe, basedir, archList):
curdir = os.getcwd()
name = recipe['name']
+ THIRD_PARTY_LIBS.append(name)
url = recipe['url']
configure = recipe.get('configure', './configure')
+ buildrecipe = recipe.get('buildrecipe', None)
install = recipe.get('install', 'make && make install DESTDIR=%s'%(
shellQuote(basedir)))
@@ -854,7 +1045,7 @@ def buildRecipe(recipe, basedir, archList):
' -arch '.join(archList),
shellQuote(SDKPATH)[1:-1],
shellQuote(basedir)[1:-1],),
- "LDFLAGS=-mmacosx-version-min=%s -syslibroot,%s -L%s/usr/local/lib -arch %s"%(
+ "LDFLAGS=-mmacosx-version-min=%s -isysroot %s -L%s/usr/local/lib -arch %s"%(
DEPTARGET,
shellQuote(SDKPATH)[1:-1],
shellQuote(basedir)[1:-1],
@@ -880,8 +1071,13 @@ def buildRecipe(recipe, basedir, archList):
print("Running configure for %s"%(name,))
runCommand(' '.join(configure_args) + ' 2>&1')
- print("Running install for %s"%(name,))
- runCommand('{ ' + install + ' ;} 2>&1')
+ if buildrecipe is not None:
+ # call special-case build recipe, e.g. for openssl
+ buildrecipe(basedir, archList)
+
+ if install is not None:
+ print("Running install for %s"%(name,))
+ runCommand('{ ' + install + ' ;} 2>&1')
print("Done %s"%(name,))
print("")
@@ -914,8 +1110,10 @@ def buildPythonDocs():
docdir = os.path.join(rootDir, 'pydocs')
curDir = os.getcwd()
os.chdir(buildDir)
- runCommand('make update')
- runCommand("make html PYTHON='%s'" % os.path.abspath(sys.executable))
+ # The Doc build changed for 3.4 (technically, for 3.4.1) and for 2.7.9
+ runCommand('make clean')
+ # Assume sphinx-build is on our PATH, checked in checkEnvironment
+ runCommand('make html')
os.chdir(curDir)
if not os.path.exists(docdir):
os.mkdir(docdir)
@@ -955,34 +1153,22 @@ def buildPython():
runCommand("%s -C --enable-framework --enable-universalsdk=%s "
"--with-universal-archs=%s "
"%s "
+ "%s "
"LDFLAGS='-g -L%s/libraries/usr/local/lib' "
"CFLAGS='-g -I%s/libraries/usr/local/include' 2>&1"%(
shellQuote(os.path.join(SRCDIR, 'configure')), shellQuote(SDKPATH),
UNIVERSALARCHS,
(' ', '--with-computed-gotos ')[PYTHON_3],
+ (' ', '--without-ensurepip ')[PYTHON_3],
shellQuote(WORKDIR)[1:-1],
shellQuote(WORKDIR)[1:-1]))
+ print("Running make touch")
+ runCommand("make touch")
+
print("Running make")
runCommand("make")
- # For deployment targets of 10.6 and higher, we build our own version
- # of Tcl and Cocoa Aqua Tk libs because the Apple-supplied Tk 8.5 is
- # out-of-date and has critical bugs. Save the _tkinter.so that was
- # linked with /Library/Frameworks/{Tck,Tk}.framework and build
- # another _tkinter.so linked with our builtin Tcl and Tk libs.
- if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)):
- runCommand("find build -name '_tkinter.so' "
- " -execdir mv '{}' _tkinter_library.so \;")
- print("Running make to build builtin _tkinter")
- runCommand("make TCLTK_INCLUDES='-I%s/libraries/usr/local/include' "
- "TCLTK_LIBS='-L%s/libraries/usr/local/lib -ltcl8.5 -ltk8.5'"%(
- shellQuote(WORKDIR)[1:-1],
- shellQuote(WORKDIR)[1:-1]))
- # make a copy which will be moved to lib-tkinter later
- runCommand("find build -name '_tkinter.so' "
- " -execdir cp -p '{}' _tkinter_builtin.so \;")
-
print("Running make install")
runCommand("make install DESTDIR=%s"%(
shellQuote(rootDir)))
@@ -1007,27 +1193,11 @@ def buildPython():
'Python.framework', 'Versions',
version, 'lib', 'python%s'%(version,))
- # If we made multiple versions of _tkinter, move them to
- # their own directories under python lib. This allows
- # users to select which to import by manipulating sys.path
- # directly or with PYTHONPATH.
-
- if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)):
- TKINTERS = ['builtin', 'library']
- tkinter_moves = [('_tkinter_' + tkn + '.so',
- os.path.join(path_to_lib, 'lib-tkinter', tkn))
- for tkn in TKINTERS]
- # Create the destination directories under lib-tkinter.
- # The permissions and uid/gid will be fixed up next.
- for tkm in tkinter_moves:
- os.makedirs(tkm[1])
-
print("Fix file modes")
frmDir = os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework')
gid = grp.getgrnam('admin').gr_gid
shared_lib_error = False
- moves_list = []
for dirpath, dirnames, filenames in os.walk(frmDir):
for dn in dirnames:
os.chmod(os.path.join(dirpath, dn), STAT_0o775)
@@ -1053,25 +1223,9 @@ def buildPython():
% (sl, p))
shared_lib_error = True
- # If this is a _tkinter variant, move it to its own directory
- # now that we have fixed its permissions and checked that it
- # was linked properly. The directory was created earlier.
- # The files are moved after the entire tree has been walked
- # since the shared library checking depends on the files
- # having unique names.
- if (DEPTARGET > '10.5') and (getVersionTuple() >= (3, 4)):
- for tkm in tkinter_moves:
- if fn == tkm[0]:
- moves_list.append(
- (p, os.path.join(tkm[1], '_tkinter.so')))
-
if shared_lib_error:
fatal("Unexpected shared library errors.")
- # Now do the moves.
- for ml in moves_list:
- shutil.move(ml[0], ml[1])
-
if PYTHON_3:
LDVERSION=None
VERSION=None
@@ -1179,6 +1333,7 @@ def patchFile(inPath, outPath):
data = data.replace('$MACOSX_DEPLOYMENT_TARGET', ''.join((DEPTARGET, ' or later')))
data = data.replace('$ARCHITECTURES', ", ".join(universal_opts_map[UNIVERSALARCHS]))
data = data.replace('$INSTALL_SIZE', installSize())
+ data = data.replace('$THIRD_PARTY_LIBS', "\\\n".join(THIRD_PARTY_LIBS))
# This one is not handy as a template variable
data = data.replace('$PYTHONFRAMEWORKINSTALLDIR', '/Library/Frameworks/Python.framework')
@@ -1187,7 +1342,9 @@ def patchFile(inPath, outPath):
fp.close()
def patchScript(inPath, outPath):
+ major, minor = getVersionMajorMinor()
data = fileContents(inPath)
+ data = data.replace('@PYMAJOR@', str(major))
data = data.replace('@PYVER@', getVersion())
fp = open(outPath, 'w')
fp.write(data)
@@ -1359,8 +1516,6 @@ def buildInstaller():
else:
patchFile(os.path.join('resources', fn), os.path.join(rsrcDir, fn))
- shutil.copy("../../LICENSE", os.path.join(rsrcDir, 'License.txt'))
-
def installSize(clear=False, _saved=[]):
if clear:
@@ -1468,12 +1623,14 @@ def main():
# Prepare the applications folder
- fn = os.path.join(WORKDIR, "_root", "Applications",
- "Python %s"%(getVersion(),), "Update Shell Profile.command")
- patchScript("scripts/postflight.patch-profile", fn)
-
folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(
getVersion(),))
+ fn = os.path.join(folder, "License.rtf")
+ patchFile("resources/License.rtf", fn)
+ fn = os.path.join(folder, "ReadMe.rtf")
+ patchFile("resources/ReadMe.rtf", fn)
+ fn = os.path.join(folder, "Update Shell Profile.command")
+ patchScript("scripts/postflight.patch-profile", fn)
os.chmod(folder, STAT_0o755)
setIcon(folder, "../Icons/Python Folder.icns")
@@ -1481,10 +1638,12 @@ def main():
buildInstaller()
# And copy the readme into the directory containing the installer
- patchFile('resources/ReadMe.txt', os.path.join(WORKDIR, 'installer', 'ReadMe.txt'))
+ patchFile('resources/ReadMe.rtf',
+ os.path.join(WORKDIR, 'installer', 'ReadMe.rtf'))
# Ditto for the license file.
- shutil.copy('../../LICENSE', os.path.join(WORKDIR, 'installer', 'License.txt'))
+ patchFile('resources/License.rtf',
+ os.path.join(WORKDIR, 'installer', 'License.rtf'))
fp = open(os.path.join(WORKDIR, 'installer', 'Build.txt'), 'w')
fp.write("# BUILD INFO\n")