Issue #14018: Backport OS X installer updates from 3.3.
This commit is contained in:
parent
8e0ae2a4f0
commit
4a96a37c66
|
@ -8,70 +8,83 @@ $DESTROOT, massages that installation to remove .pyc files and such, creates
|
|||
an Installer package from the installation plus other files in ``resources``
|
||||
and ``scripts`` and placed that on a ``.dmg`` disk image.
|
||||
|
||||
As of Python 2.7.x and 3.2, PSF practice is to build two installer variants
|
||||
for each release:
|
||||
For Python 2.7.x and 3.2.x, PSF practice is to build two installer variants
|
||||
for each release.
|
||||
|
||||
1. 32-bit-only, i386 and PPC universal, capable on running on all machines
|
||||
supported by Mac OS X 10.3.9 through (at least) 10.6::
|
||||
supported by Mac OS X 10.3.9 through (at least) 10.8::
|
||||
|
||||
python build-installer.py \
|
||||
/usr/bin/python build-installer.py \
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.4u.sdk \
|
||||
--universal-archs=32-bit \
|
||||
--dep-target=10.3
|
||||
# These are the current default options
|
||||
|
||||
- builds the following third-party libraries
|
||||
|
||||
* Bzip2
|
||||
* Zlib 1.2.3
|
||||
* GNU Readline (GPL)
|
||||
* SQLite 3
|
||||
* NCurses
|
||||
* GNU Readline (GPL)
|
||||
* SQLite 3.7.13
|
||||
* Zlib 1.2.3
|
||||
* Oracle Sleepycat DB 4.8 (Python 2.x only)
|
||||
|
||||
- requires ActiveState ``Tcl/Tk 8.4`` (currently 8.4.19) to be installed for building
|
||||
|
||||
- current target build environment:
|
||||
- recommended build environment:
|
||||
|
||||
* Mac OS X 10.5.8 PPC or Intel
|
||||
* Xcode 3.1.4 (or later)
|
||||
* Xcode 3.1.4
|
||||
* ``MacOSX10.4u`` SDK (later SDKs do not support PPC G3 processors)
|
||||
* ``MACOSX_DEPLOYMENT_TARGET=10.3``
|
||||
* Apple ``gcc-4.0``
|
||||
* Python 2.n (n >= 4) for documentation build with Sphinx
|
||||
* system Python 2.5 for documentation build with Sphinx
|
||||
|
||||
- alternate build environments:
|
||||
|
||||
* Mac OS X 10.4.11 with Xcode 2.5
|
||||
* Mac OS X 10.6.6 with Xcode 3.2.5
|
||||
* Mac OS X 10.6.8 with Xcode 3.2.6
|
||||
- need to change ``/System/Library/Frameworks/{Tcl,Tk}.framework/Version/Current`` to ``8.4``
|
||||
* Note Xcode 4.* does not support building for PPC so cannot be used for this build
|
||||
|
||||
|
||||
2. 64-bit / 32-bit, x86_64 and i386 universal, for OS X 10.6 (and later)::
|
||||
|
||||
python build-installer.py \
|
||||
/usr/bin/python build-installer.py \
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.6.sdk \
|
||||
--universal-archs=intel \
|
||||
--dep-target=10.6
|
||||
|
||||
- builds the following third-party libraries
|
||||
|
||||
* NCurses 5.9 (http://bugs.python.org/issue15037)
|
||||
* SQLite 3.7.13
|
||||
|
||||
- uses system-supplied versions of third-party libraries
|
||||
|
||||
|
||||
* readline module links with Apple BSD editline (libedit)
|
||||
* builds Oracle Sleepycat DB 4.8 (Python 2.x only)
|
||||
|
||||
- requires ActiveState Tcl/Tk 8.5.9 (or later) to be installed for building
|
||||
|
||||
- current target build environment:
|
||||
|
||||
* Mac OS X 10.6.6 (or later)
|
||||
* Xcode 3.2.5 (or later)
|
||||
- recommended build environment:
|
||||
|
||||
* Mac OS X 10.6.8 (or later)
|
||||
* Xcode 3.2.6
|
||||
* ``MacOSX10.6`` SDK
|
||||
* ``MACOSX_DEPLOYMENT_TARGET=10.6``
|
||||
* Apple ``gcc-4.2``
|
||||
* Python 2.n (n >= 4) for documentation build with Sphinx
|
||||
* system Python 2.6 for documentation build with Sphinx
|
||||
|
||||
- alternate build environments:
|
||||
|
||||
* none
|
||||
* none. Xcode 4.x currently supplies two C compilers.
|
||||
``llvm-gcc-4.2.1`` has been found to miscompile Python 3.3.x and
|
||||
produce a non-functional Python executable. As it appears to be
|
||||
considered a migration aid by Apple and is not likely to be fixed,
|
||||
its use should be avoided. The other compiler, ``clang``, has been
|
||||
undergoing rapid development. While it appears to have become
|
||||
production-ready in the most recent Xcode 4 releases (Xcode 4.5.x
|
||||
as of this writing), there are still some open issues when
|
||||
building Python and there has not yet been the level of exposure in
|
||||
production environments that the Xcode 3 gcc-4.2 compiler has had.
|
||||
|
||||
|
||||
General Prerequisites
|
||||
|
@ -87,6 +100,11 @@ General Prerequisites
|
|||
* It is safest to start each variant build with an empty source directory
|
||||
populated with a fresh copy of the untarred source.
|
||||
|
||||
* It is recommended that you remove any existing installed version of the
|
||||
Python being built::
|
||||
|
||||
sudo rm -rf /Library/Frameworks/Python.framework/Versions/n.n
|
||||
|
||||
|
||||
The Recipe
|
||||
----------
|
||||
|
@ -107,9 +125,9 @@ Building other universal installers
|
|||
...................................
|
||||
|
||||
It is also possible to build a 4-way universal installer that runs on
|
||||
OS X Leopard or later::
|
||||
OS X 10.5 Leopard or later::
|
||||
|
||||
python 2.6 /build-installer.py \
|
||||
/usr/bin/python /build-installer.py \
|
||||
--dep-target=10.5
|
||||
--universal-archs=all
|
||||
--sdk-path=/Developer/SDKs/MacOSX10.5.sdk
|
||||
|
@ -120,7 +138,8 @@ also that you are building on at least OS X 10.5. 4-way includes
|
|||
variants can only be run on G5 machines running 10.5. Note that,
|
||||
while OS X 10.6 is only supported on Intel-based machines, it is possible
|
||||
to run ``ppc`` (32-bit) executables unmodified thanks to the Rosetta ppc
|
||||
emulation in OS X 10.5 and 10.6.
|
||||
emulation in OS X 10.5 and 10.6. The 4-way installer variant must be
|
||||
built with Xcode 3. It is not regularly built or tested.
|
||||
|
||||
Other ``--universal-archs`` options are ``64-bit`` (``x86_64``, ``ppc64``),
|
||||
and ``3-way`` (``ppc``, ``i386``, ``x86_64``). None of these options
|
||||
|
@ -133,15 +152,21 @@ Testing
|
|||
Ideally, the resulting binaries should be installed and the test suite run
|
||||
on all supported OS X releases and architectures. As a practical matter,
|
||||
that is generally not possible. At a minimum, variant 1 should be run on
|
||||
at least one Intel, one PPC G4, and one PPC G3 system and one each of
|
||||
OS X 10.6, 10.5, 10.4, and 10.3.9. Not all tests run on 10.3.9.
|
||||
Variant 2 should be run on 10.6 in both 32-bit and 64-bit modes.::
|
||||
a PPC G4 system with OS X 10.5 and at least one Intel system running OS X
|
||||
10.8, 10.7, 10.6, or 10.5. Variant 2 should be run on 10.8, 10.7, and 10.6
|
||||
systems in both 32-bit and 64-bit modes.::
|
||||
|
||||
arch -i386 /usr/local/bin/pythonn.n -m test.regrtest -w -u all
|
||||
arch -X86_64 /usr/local/bin/pythonn.n -m test.regrtest -w -u all
|
||||
/usr/local/bin/pythonn.n -m test -w -u all,-largefile
|
||||
/usr/local/bin/pythonn.n-32 -m test -w -u all
|
||||
|
||||
Certain tests will be skipped and some cause the interpreter to fail
|
||||
which will likely generate ``Python quit unexpectedly`` alert messages
|
||||
to be generated at several points during a test run. These can
|
||||
be ignored.
|
||||
to be generated at several points during a test run. These are normal
|
||||
during testing and can be ignored.
|
||||
|
||||
It is also recommend to launch IDLE and verify that it is at least
|
||||
functional. Double-click on the IDLE app icon in ``/Applications/Pythonn.n``.
|
||||
It should also be tested from the command line::
|
||||
|
||||
/usr/local/bin/idlen.n
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
This script is used to build "official" universal installers on Mac OS X.
|
||||
It requires at least Mac OS X 10.4, Xcode 2.2 and the 10.4u SDK for
|
||||
It requires at least Mac OS X 10.5, Xcode 3, and the 10.4u SDK for
|
||||
32-bit builds. 64-bit or four-way universal builds require at least
|
||||
OS X 10.5 and the 10.5 SDK.
|
||||
|
||||
|
@ -10,18 +10,41 @@ 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.
|
||||
|
||||
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
|
||||
Tcl/Tk 8.4 (for OS X 10.4 and 10.5 deployment targets) or Tcl/TK 8.5
|
||||
(for 10.6 or later) installed in /Library/Frameworks. When installed,
|
||||
the Python built by this script will attempt to dynamically link first to
|
||||
Tcl and Tk frameworks in /Library/Frameworks if available otherwise fall
|
||||
back to the ones in /System/Library/Framework. For the build, we recommend
|
||||
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).
|
||||
|
||||
Usage: see USAGE variable in the script.
|
||||
"""
|
||||
import platform, os, sys, getopt, textwrap, shutil, urllib2, stat, time, pwd
|
||||
import grp
|
||||
import platform, os, sys, getopt, textwrap, shutil, stat, time, pwd, grp
|
||||
try:
|
||||
import urllib2 as urllib_request
|
||||
except ImportError:
|
||||
import urllib.request as urllib_request
|
||||
|
||||
STAT_0o755 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
|
||||
| stat.S_IRGRP | stat.S_IXGRP
|
||||
| stat.S_IROTH | stat.S_IXOTH )
|
||||
|
||||
STAT_0o775 = ( stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
|
||||
| stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP
|
||||
| stat.S_IROTH | stat.S_IXOTH )
|
||||
|
||||
INCLUDE_TIMESTAMP = 1
|
||||
VERBOSE = 1
|
||||
|
||||
from plistlib import Plist
|
||||
|
||||
import MacOS
|
||||
|
||||
try:
|
||||
from plistlib import writePlist
|
||||
except ImportError:
|
||||
|
@ -42,20 +65,35 @@ def grepValue(fn, variable):
|
|||
if ln.startswith(variable):
|
||||
value = ln[len(variable):].strip()
|
||||
return value[1:-1]
|
||||
raise RuntimeError, "Cannot find variable %s" % variable[:-1]
|
||||
raise RuntimeError("Cannot find variable %s" % variable[:-1])
|
||||
|
||||
_cache_getVersion = None
|
||||
|
||||
def getVersion():
|
||||
return grepValue(os.path.join(SRCDIR, 'configure'), 'PACKAGE_VERSION')
|
||||
global _cache_getVersion
|
||||
if _cache_getVersion is None:
|
||||
_cache_getVersion = grepValue(
|
||||
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)])
|
||||
|
||||
_cache_getFullVersion = None
|
||||
|
||||
def getFullVersion():
|
||||
global _cache_getFullVersion
|
||||
if _cache_getFullVersion is not None:
|
||||
return _cache_getFullVersion
|
||||
fn = os.path.join(SRCDIR, 'Include', 'patchlevel.h')
|
||||
for ln in open(fn):
|
||||
if 'PY_VERSION' in ln:
|
||||
return ln.split()[-1][1:-1]
|
||||
raise RuntimeError, "Cannot find full version??"
|
||||
_cache_getFullVersion = ln.split()[-1][1:-1]
|
||||
return _cache_getFullVersion
|
||||
raise RuntimeError("Cannot find full version??")
|
||||
|
||||
# The directory we'll use to create the build (will be erased and recreated)
|
||||
WORKDIR = "/tmp/_py"
|
||||
|
@ -111,13 +149,15 @@ SRCDIR = os.path.dirname(
|
|||
DEPTARGET = '10.3'
|
||||
|
||||
target_cc_map = {
|
||||
'10.3': 'gcc-4.0',
|
||||
'10.4': 'gcc-4.0',
|
||||
'10.5': 'gcc-4.0',
|
||||
'10.6': 'gcc-4.2',
|
||||
'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++'),
|
||||
}
|
||||
|
||||
CC = target_cc_map[DEPTARGET]
|
||||
CC, CXX = target_cc_map[DEPTARGET]
|
||||
|
||||
PYTHON_3 = getVersionTuple() >= (3, 0)
|
||||
|
||||
|
@ -135,6 +175,13 @@ USAGE = textwrap.dedent("""\
|
|||
--universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r)
|
||||
""")% globals()
|
||||
|
||||
# Dict of object file names with shared library names to check after building.
|
||||
# This is to ensure that we ended up dynamically linking with the shared
|
||||
# library paths and versions we expected. For example:
|
||||
# EXPECTED_SHARED_LIBS['_tkinter.so'] = [
|
||||
# '/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl',
|
||||
# '/Library/Frameworks/Tk.framework/Versions/8.5/Tk']
|
||||
EXPECTED_SHARED_LIBS = {}
|
||||
|
||||
# Instructions for building libraries that are necessary for building a
|
||||
# batteries included python.
|
||||
|
@ -143,6 +190,75 @@ USAGE = textwrap.dedent("""\
|
|||
def library_recipes():
|
||||
result = []
|
||||
|
||||
LT_10_5 = bool(DEPTARGET < '10.5')
|
||||
|
||||
if getVersionTuple() >= (3, 3):
|
||||
result.extend([
|
||||
dict(
|
||||
name="XZ 5.0.3",
|
||||
url="http://tukaani.org/xz/xz-5.0.3.tar.gz",
|
||||
checksum='fefe52f9ecd521de2a8ce38c21a27574',
|
||||
configure_pre=[
|
||||
'--disable-dependency-tracking',
|
||||
]
|
||||
),
|
||||
])
|
||||
|
||||
result.extend([
|
||||
dict(
|
||||
name="NCurses 5.9",
|
||||
url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz",
|
||||
checksum='8cb9c412e5f2d96bc6f459aa8c6282a1',
|
||||
configure_pre=[
|
||||
"--enable-widec",
|
||||
"--without-cxx",
|
||||
"--without-cxx-binding",
|
||||
"--without-ada",
|
||||
"--without-curses-h",
|
||||
"--enable-shared",
|
||||
"--with-shared",
|
||||
"--without-debug",
|
||||
"--without-normal",
|
||||
"--without-tests",
|
||||
"--without-manpages",
|
||||
"--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(),),
|
||||
],
|
||||
patchscripts=[
|
||||
("ftp://invisible-island.net/ncurses//5.9/ncurses-5.9-20120616-patch.sh.bz2",
|
||||
"f54bf02a349f96a7c4f0d00922f3a0d4"),
|
||||
],
|
||||
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="SQLite 3.7.13",
|
||||
url="http://www.sqlite.org/sqlite-autoconf-3071300.tar.gz",
|
||||
checksum='c97df403e8a3d5b67bb408fcd6aabd8e',
|
||||
extra_cflags=('-Os '
|
||||
'-DSQLITE_ENABLE_FTS4 '
|
||||
'-DSQLITE_ENABLE_FTS3_PARENTHESIS '
|
||||
'-DSQLITE_ENABLE_RTREE '
|
||||
'-DSQLITE_TCL=0 '
|
||||
'%s' % ('','-DSQLITE_WITHOUT_ZONEMALLOC ')[LT_10_5]),
|
||||
configure_pre=[
|
||||
'--enable-threadsafe',
|
||||
'--enable-shared=no',
|
||||
'--enable-static=yes',
|
||||
'--disable-readline',
|
||||
'--disable-dependency-tracking',
|
||||
]
|
||||
),
|
||||
])
|
||||
|
||||
if DEPTARGET < '10.5':
|
||||
result.extend([
|
||||
dict(
|
||||
|
@ -150,8 +266,8 @@ def library_recipes():
|
|||
url="http://bzip.org/1.0.6/bzip2-1.0.6.tar.gz",
|
||||
checksum='00b516f4704d4a7cb50a1d97e6e8e15b',
|
||||
configure=None,
|
||||
install='make install CC=%s PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
|
||||
CC,
|
||||
install='make install CC=%s CXX=%s, PREFIX=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
|
||||
CC, CXX,
|
||||
shellQuote(os.path.join(WORKDIR, 'libraries')),
|
||||
' -arch '.join(ARCHLIST),
|
||||
SDKPATH,
|
||||
|
@ -162,8 +278,8 @@ def library_recipes():
|
|||
url="http://www.gzip.org/zlib/zlib-1.2.3.tar.gz",
|
||||
checksum='debc62758716a169df9f62e6ab2bc634',
|
||||
configure=None,
|
||||
install='make install CC=%s prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
|
||||
CC,
|
||||
install='make install CC=%s CXX=%s, prefix=%s/usr/local/ CFLAGS="-arch %s -isysroot %s"'%(
|
||||
CC, CXX,
|
||||
shellQuote(os.path.join(WORKDIR, 'libraries')),
|
||||
' -arch '.join(ARCHLIST),
|
||||
SDKPATH,
|
||||
|
@ -178,58 +294,12 @@ def library_recipes():
|
|||
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-6.1-patches/readline61-001',
|
||||
'http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002',
|
||||
('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-001',
|
||||
'c642f2e84d820884b0bf9fd176bc6c3f'),
|
||||
('http://ftp.gnu.org/pub/gnu/readline/readline-6.1-patches/readline61-002',
|
||||
'1a76781a1ea734e831588285db7ec9b1'),
|
||||
]
|
||||
),
|
||||
dict(
|
||||
name="SQLite 3.7.4",
|
||||
url="http://www.sqlite.org/sqlite-autoconf-3070400.tar.gz",
|
||||
checksum='8f0c690bfb33c3cbbc2471c3d9ba0158',
|
||||
configure_env=('CFLAGS="-Os'
|
||||
' -DSQLITE_ENABLE_FTS3'
|
||||
' -DSQLITE_ENABLE_FTS3_PARENTHESIS'
|
||||
' -DSQLITE_ENABLE_RTREE'
|
||||
' -DSQLITE_TCL=0'
|
||||
'"'),
|
||||
configure_pre=[
|
||||
'--enable-threadsafe',
|
||||
'--enable-shared=no',
|
||||
'--enable-static=yes',
|
||||
'--disable-readline',
|
||||
'--disable-dependency-tracking',
|
||||
]
|
||||
),
|
||||
dict(
|
||||
name="NCurses 5.5",
|
||||
url="http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.5.tar.gz",
|
||||
checksum='e73c1ac10b4bfc46db43b2ddfd6244ef',
|
||||
configure_pre=[
|
||||
"--enable-widec",
|
||||
"--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(),
|
||||
),
|
||||
),
|
||||
])
|
||||
|
||||
if not PYTHON_3:
|
||||
|
@ -298,9 +368,7 @@ def pkg_recipes():
|
|||
source="/pydocs",
|
||||
readme="""\
|
||||
This package installs the python documentation at a location
|
||||
that is useable for pydoc and IDLE. If you have installed Xcode
|
||||
it will also install a link to the documentation in
|
||||
/Developer/Documentation/Python
|
||||
that is useable for pydoc and IDLE.
|
||||
""",
|
||||
postflight="scripts/postflight.documentation",
|
||||
required=False,
|
||||
|
@ -326,7 +394,7 @@ def pkg_recipes():
|
|||
),
|
||||
]
|
||||
|
||||
if DEPTARGET < '10.4':
|
||||
if DEPTARGET < '10.4' and not PYTHON_3:
|
||||
result.append(
|
||||
dict(
|
||||
name="PythonSystemFixes",
|
||||
|
@ -358,7 +426,7 @@ def fileContents(fn):
|
|||
"""
|
||||
Return the contents of the named file
|
||||
"""
|
||||
return open(fn, 'rb').read()
|
||||
return open(fn, 'r').read()
|
||||
|
||||
def runCommand(commandline):
|
||||
"""
|
||||
|
@ -370,7 +438,7 @@ def runCommand(commandline):
|
|||
xit = fd.close()
|
||||
if xit is not None:
|
||||
sys.stdout.write(data)
|
||||
raise RuntimeError, "command failed: %s"%(commandline,)
|
||||
raise RuntimeError("command failed: %s"%(commandline,))
|
||||
|
||||
if VERBOSE:
|
||||
sys.stdout.write(data); sys.stdout.flush()
|
||||
|
@ -381,7 +449,7 @@ def captureCommand(commandline):
|
|||
xit = fd.close()
|
||||
if xit is not None:
|
||||
sys.stdout.write(data)
|
||||
raise RuntimeError, "command failed: %s"%(commandline,)
|
||||
raise RuntimeError("command failed: %s"%(commandline,))
|
||||
|
||||
return data
|
||||
|
||||
|
@ -423,39 +491,60 @@ def checkEnvironment():
|
|||
# Because we only support dynamic load of only one major/minor version of
|
||||
# Tcl/Tk, ensure:
|
||||
# 1. there are no user-installed frameworks of Tcl/Tk with version
|
||||
# higher than the Apple-supplied system version
|
||||
# 2. there is a user-installed framework in /Library/Frameworks with the
|
||||
# same version as the system version. This allows users to choose
|
||||
# to install a newer patch level.
|
||||
# higher than the Apple-supplied system version in
|
||||
# SDKROOT/System/Library/Frameworks
|
||||
# 2. there is a user-installed framework (usually ActiveTcl) in (or linked
|
||||
# in) SDKROOT/Library/Frameworks with the same version as the system
|
||||
# version. This allows users to choose to install a newer patch level.
|
||||
|
||||
frameworks = {}
|
||||
for framework in ['Tcl', 'Tk']:
|
||||
#fw = dict(lower=framework.lower(),
|
||||
# upper=framework.upper(),
|
||||
# cap=framework.capitalize())
|
||||
#fwpth = "Library/Frameworks/%(cap)s.framework/%(lower)sConfig.sh" % fw
|
||||
fwpth = 'Library/Frameworks/Tcl.framework/Versions/Current'
|
||||
fwpth = 'Library/Frameworks/%s.framework/Versions/Current' % framework
|
||||
sysfw = os.path.join(SDKPATH, 'System', fwpth)
|
||||
libfw = os.path.join('/', fwpth)
|
||||
libfw = os.path.join(SDKPATH, fwpth)
|
||||
usrfw = os.path.join(os.getenv('HOME'), fwpth)
|
||||
#version = "%(upper)s_VERSION" % fw
|
||||
frameworks[framework] = os.readlink(sysfw)
|
||||
if not os.path.exists(libfw):
|
||||
fatal("Please install a link to a current %s %s as %s so "
|
||||
"the user can override the system framework."
|
||||
% (framework, frameworks[framework], libfw))
|
||||
if os.readlink(libfw) != os.readlink(sysfw):
|
||||
fatal("Version of %s must match %s" % (libfw, sysfw) )
|
||||
if os.path.exists(usrfw):
|
||||
fatal("Please rename %s to avoid possible dynamic load issues."
|
||||
% usrfw)
|
||||
|
||||
if frameworks['Tcl'] != frameworks['Tk']:
|
||||
fatal("The Tcl and Tk frameworks are not the same version.")
|
||||
|
||||
# add files to check after build
|
||||
EXPECTED_SHARED_LIBS['_tkinter.so'] = [
|
||||
"/Library/Frameworks/Tcl.framework/Versions/%s/Tcl"
|
||||
% frameworks['Tcl'],
|
||||
"/Library/Frameworks/Tk.framework/Versions/%s/Tk"
|
||||
% frameworks['Tk'],
|
||||
]
|
||||
|
||||
# Remove inherited environment variables which might influence build
|
||||
environ_var_prefixes = ['CPATH', 'C_INCLUDE_', 'DYLD_', 'LANG', 'LC_',
|
||||
'LD_', 'LIBRARY_', 'PATH', 'PYTHON']
|
||||
for ev in list(os.environ):
|
||||
for prefix in environ_var_prefixes:
|
||||
if ev.startswith(prefix) :
|
||||
print "INFO: deleting environment variable %s=%s" % (
|
||||
ev, os.environ[ev])
|
||||
print("INFO: deleting environment variable %s=%s" % (
|
||||
ev, os.environ[ev]))
|
||||
del os.environ[ev]
|
||||
|
||||
os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin'
|
||||
print "Setting default PATH: %s"%(os.environ['PATH'])
|
||||
base_path = '/bin:/sbin:/usr/bin:/usr/sbin'
|
||||
if 'SDK_TOOLS_BIN' in os.environ:
|
||||
base_path = os.environ['SDK_TOOLS_BIN'] + ':' + base_path
|
||||
# Xcode 2.5 on OS X 10.4 does not include SetFile in its usr/bin;
|
||||
# add its fixed location here if it exists
|
||||
OLD_DEVELOPER_TOOLS = '/Developer/Tools'
|
||||
if os.path.isdir(OLD_DEVELOPER_TOOLS):
|
||||
base_path = base_path + ':' + OLD_DEVELOPER_TOOLS
|
||||
os.environ['PATH'] = base_path
|
||||
print("Setting default PATH: %s"%(os.environ['PATH']))
|
||||
|
||||
|
||||
def parseOptions(args=None):
|
||||
|
@ -463,7 +552,7 @@ def parseOptions(args=None):
|
|||
Parse arguments and update global settings.
|
||||
"""
|
||||
global WORKDIR, DEPSRC, SDKPATH, SRCDIR, DEPTARGET
|
||||
global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC
|
||||
global UNIVERSALOPTS, UNIVERSALARCHS, ARCHLIST, CC, CXX
|
||||
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
|
@ -472,18 +561,18 @@ def parseOptions(args=None):
|
|||
options, args = getopt.getopt(args, '?hb',
|
||||
[ 'build-dir=', 'third-party=', 'sdk-path=' , 'src-dir=',
|
||||
'dep-target=', 'universal-archs=', 'help' ])
|
||||
except getopt.error, msg:
|
||||
print msg
|
||||
except getopt.GetoptError:
|
||||
print(sys.exc_info()[1])
|
||||
sys.exit(1)
|
||||
|
||||
if args:
|
||||
print "Additional arguments"
|
||||
print("Additional arguments")
|
||||
sys.exit(1)
|
||||
|
||||
deptarget = None
|
||||
for k, v in options:
|
||||
if k in ('-h', '-?', '--help'):
|
||||
print USAGE
|
||||
print(USAGE)
|
||||
sys.exit(0)
|
||||
|
||||
elif k in ('-d', '--build-dir'):
|
||||
|
@ -511,27 +600,28 @@ def parseOptions(args=None):
|
|||
# target
|
||||
DEPTARGET = default_target_map.get(v, '10.3')
|
||||
else:
|
||||
raise NotImplementedError, v
|
||||
raise NotImplementedError(v)
|
||||
|
||||
else:
|
||||
raise NotImplementedError, k
|
||||
raise NotImplementedError(k)
|
||||
|
||||
SRCDIR=os.path.abspath(SRCDIR)
|
||||
WORKDIR=os.path.abspath(WORKDIR)
|
||||
SDKPATH=os.path.abspath(SDKPATH)
|
||||
DEPSRC=os.path.abspath(DEPSRC)
|
||||
|
||||
CC=target_cc_map[DEPTARGET]
|
||||
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 ""
|
||||
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("")
|
||||
|
||||
|
||||
|
||||
|
@ -576,31 +666,18 @@ def extractArchive(builddir, archiveName):
|
|||
xit = fp.close()
|
||||
if xit is not None:
|
||||
sys.stdout.write(data)
|
||||
raise RuntimeError, "Cannot extract %s"%(archiveName,)
|
||||
raise RuntimeError("Cannot extract %s"%(archiveName,))
|
||||
|
||||
return os.path.join(builddir, retval)
|
||||
|
||||
finally:
|
||||
os.chdir(curdir)
|
||||
|
||||
KNOWNSIZES = {
|
||||
"http://ftp.gnu.org/pub/gnu/readline/readline-5.1.tar.gz": 7952742,
|
||||
"http://downloads.sleepycat.com/db-4.4.20.tar.gz": 2030276,
|
||||
}
|
||||
|
||||
def downloadURL(url, fname):
|
||||
"""
|
||||
Download the contents of the url into the file.
|
||||
"""
|
||||
try:
|
||||
size = os.path.getsize(fname)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
if KNOWNSIZES.get(url) == size:
|
||||
print "Using existing file for", url
|
||||
return
|
||||
fpIn = urllib2.urlopen(url)
|
||||
fpIn = urllib_request.urlopen(url)
|
||||
fpOut = open(fname, 'wb')
|
||||
block = fpIn.read(10240)
|
||||
try:
|
||||
|
@ -615,6 +692,24 @@ def downloadURL(url, fname):
|
|||
except:
|
||||
pass
|
||||
|
||||
def verifyThirdPartyFile(url, checksum, fname):
|
||||
"""
|
||||
Download file from url to filename fname if it does not already exist.
|
||||
Abort if file contents does not match supplied md5 checksum.
|
||||
"""
|
||||
name = os.path.basename(fname)
|
||||
if os.path.exists(fname):
|
||||
print("Using local copy of %s"%(name,))
|
||||
else:
|
||||
print("Did not find local copy of %s"%(name,))
|
||||
print("Downloading %s"%(name,))
|
||||
downloadURL(url, fname)
|
||||
print("Archive for %s stored as %s"%(name, fname))
|
||||
if os.system(
|
||||
'MD5=$(openssl md5 %s) ; test "${MD5##*= }" = "%s"'
|
||||
% (shellQuote(fname), checksum) ):
|
||||
fatal('MD5 checksum mismatch for file %s' % fname)
|
||||
|
||||
def buildRecipe(recipe, basedir, archList):
|
||||
"""
|
||||
Build software using a recipe. This function does the
|
||||
|
@ -635,17 +730,8 @@ def buildRecipe(recipe, basedir, archList):
|
|||
if not os.path.exists(DEPSRC):
|
||||
os.mkdir(DEPSRC)
|
||||
|
||||
|
||||
if os.path.exists(sourceArchive):
|
||||
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)
|
||||
|
||||
print "Extracting archive for %s"%(name,)
|
||||
verifyThirdPartyFile(url, recipe['checksum'], sourceArchive)
|
||||
print("Extracting archive for %s"%(name,))
|
||||
buildDir=os.path.join(WORKDIR, '_bld')
|
||||
if not os.path.exists(buildDir):
|
||||
os.mkdir(buildDir)
|
||||
|
@ -655,18 +741,31 @@ def buildRecipe(recipe, basedir, archList):
|
|||
if 'buildDir' in recipe:
|
||||
os.chdir(recipe['buildDir'])
|
||||
|
||||
|
||||
for fn in recipe.get('patches', ()):
|
||||
if fn.startswith('http://'):
|
||||
# Download the patch before applying it.
|
||||
path = os.path.join(DEPSRC, os.path.basename(fn))
|
||||
downloadURL(fn, path)
|
||||
fn = path
|
||||
|
||||
fn = os.path.join(curdir, fn)
|
||||
for patch in recipe.get('patches', ()):
|
||||
if isinstance(patch, tuple):
|
||||
url, checksum = patch
|
||||
fn = os.path.join(DEPSRC, os.path.basename(url))
|
||||
verifyThirdPartyFile(url, checksum, fn)
|
||||
else:
|
||||
# patch is a file in the source directory
|
||||
fn = os.path.join(curdir, patch)
|
||||
runCommand('patch -p%s < %s'%(recipe.get('patchlevel', 1),
|
||||
shellQuote(fn),))
|
||||
|
||||
for patchscript in recipe.get('patchscripts', ()):
|
||||
if isinstance(patchscript, tuple):
|
||||
url, checksum = patchscript
|
||||
fn = os.path.join(DEPSRC, os.path.basename(url))
|
||||
verifyThirdPartyFile(url, checksum, fn)
|
||||
else:
|
||||
# patch is a file in the source directory
|
||||
fn = os.path.join(curdir, patchscript)
|
||||
if fn.endswith('.bz2'):
|
||||
runCommand('bunzip2 -fk %s' % shellQuote(fn))
|
||||
fn = fn[:-4]
|
||||
runCommand('sh %s' % shellQuote(fn))
|
||||
os.unlink(fn)
|
||||
|
||||
if configure is not None:
|
||||
configure_args = [
|
||||
"--prefix=/usr/local",
|
||||
|
@ -685,40 +784,44 @@ def buildRecipe(recipe, basedir, archList):
|
|||
|
||||
if recipe.get('useLDFlags', 1):
|
||||
configure_args.extend([
|
||||
"CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
|
||||
"CFLAGS=%s-mmacosx-version-min=%s -arch %s -isysroot %s "
|
||||
"-I%s/usr/local/include"%(
|
||||
recipe.get('extra_cflags', ''),
|
||||
DEPTARGET,
|
||||
' -arch '.join(archList),
|
||||
shellQuote(SDKPATH)[1:-1],
|
||||
shellQuote(basedir)[1:-1],),
|
||||
"LDFLAGS=-syslibroot,%s -L%s/usr/local/lib -arch %s"%(
|
||||
"LDFLAGS=-mmacosx-version-min=%s -syslibroot,%s -L%s/usr/local/lib -arch %s"%(
|
||||
DEPTARGET,
|
||||
shellQuote(SDKPATH)[1:-1],
|
||||
shellQuote(basedir)[1:-1],
|
||||
' -arch '.join(archList)),
|
||||
])
|
||||
else:
|
||||
configure_args.extend([
|
||||
"CFLAGS=-arch %s -isysroot %s -I%s/usr/local/include"%(
|
||||
"CFLAGS=%s-mmacosx-version-min=%s -arch %s -isysroot %s "
|
||||
"-I%s/usr/local/include"%(
|
||||
recipe.get('extra_cflags', ''),
|
||||
DEPTARGET,
|
||||
' -arch '.join(archList),
|
||||
shellQuote(SDKPATH)[1:-1],
|
||||
shellQuote(basedir)[1:-1],),
|
||||
])
|
||||
|
||||
if 'configure_post' in recipe:
|
||||
configure_args = configure_args = list(recipe['configure_post'])
|
||||
configure_args = configure_args + list(recipe['configure_post'])
|
||||
|
||||
configure_args.insert(0, configure)
|
||||
configure_args = [ shellQuote(a) for a in configure_args ]
|
||||
|
||||
if 'configure_env' in recipe:
|
||||
configure_args.insert(0, recipe['configure_env'])
|
||||
|
||||
print "Running configure for %s"%(name,)
|
||||
print("Running configure for %s"%(name,))
|
||||
runCommand(' '.join(configure_args) + ' 2>&1')
|
||||
|
||||
print "Running install for %s"%(name,)
|
||||
print("Running install for %s"%(name,))
|
||||
runCommand('{ ' + install + ' ;} 2>&1')
|
||||
|
||||
print "Done %s"%(name,)
|
||||
print ""
|
||||
print("Done %s"%(name,))
|
||||
print("")
|
||||
|
||||
os.chdir(curdir)
|
||||
|
||||
|
@ -726,9 +829,9 @@ def buildLibraries():
|
|||
"""
|
||||
Build our dependencies into $WORKDIR/libraries/usr/local
|
||||
"""
|
||||
print ""
|
||||
print "Building required libraries"
|
||||
print ""
|
||||
print("")
|
||||
print("Building required libraries")
|
||||
print("")
|
||||
universal = os.path.join(WORKDIR, 'libraries')
|
||||
os.mkdir(universal)
|
||||
os.makedirs(os.path.join(universal, 'usr', 'local', 'lib'))
|
||||
|
@ -742,7 +845,7 @@ def buildLibraries():
|
|||
def buildPythonDocs():
|
||||
# This stores the documentation as Resources/English.lproj/Documentation
|
||||
# inside the framwork. pydoc and IDLE will pick it up there.
|
||||
print "Install python documentation"
|
||||
print("Install python documentation")
|
||||
rootDir = os.path.join(WORKDIR, '_root')
|
||||
buildDir = os.path.join('../../Doc')
|
||||
docdir = os.path.join(rootDir, 'pydocs')
|
||||
|
@ -757,7 +860,7 @@ def buildPythonDocs():
|
|||
|
||||
|
||||
def buildPython():
|
||||
print "Building a universal python for %s architectures" % UNIVERSALARCHS
|
||||
print("Building a universal python for %s architectures" % UNIVERSALARCHS)
|
||||
|
||||
buildDir = os.path.join(WORKDIR, '_bld', 'python')
|
||||
rootDir = os.path.join(WORKDIR, '_root')
|
||||
|
@ -785,7 +888,7 @@ def buildPython():
|
|||
# will find them during its extension import sanity checks.
|
||||
os.environ['DYLD_LIBRARY_PATH'] = os.path.join(WORKDIR,
|
||||
'libraries', 'usr', 'local', 'lib')
|
||||
print "Running configure..."
|
||||
print("Running configure...")
|
||||
runCommand("%s -C --enable-framework --enable-universalsdk=%s "
|
||||
"--with-universal-archs=%s "
|
||||
"%s "
|
||||
|
@ -797,19 +900,19 @@ def buildPython():
|
|||
shellQuote(WORKDIR)[1:-1],
|
||||
shellQuote(WORKDIR)[1:-1]))
|
||||
|
||||
print "Running make"
|
||||
print("Running make")
|
||||
runCommand("make")
|
||||
|
||||
print "Running make install"
|
||||
print("Running make install")
|
||||
runCommand("make install DESTDIR=%s"%(
|
||||
shellQuote(rootDir)))
|
||||
|
||||
print "Running make frameworkinstallextras"
|
||||
print("Running make frameworkinstallextras")
|
||||
runCommand("make frameworkinstallextras DESTDIR=%s"%(
|
||||
shellQuote(rootDir)))
|
||||
|
||||
del os.environ['DYLD_LIBRARY_PATH']
|
||||
print "Copying required shared libraries"
|
||||
print("Copying required shared libraries")
|
||||
if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')):
|
||||
runCommand("mv %s/* %s"%(
|
||||
shellQuote(os.path.join(
|
||||
|
@ -820,16 +923,16 @@ def buildPython():
|
|||
'Python.framework', 'Versions', getVersion(),
|
||||
'lib'))))
|
||||
|
||||
print "Fix file modes"
|
||||
print("Fix file modes")
|
||||
frmDir = os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework')
|
||||
gid = grp.getgrnam('admin').gr_gid
|
||||
|
||||
shared_lib_error = False
|
||||
for dirpath, dirnames, filenames in os.walk(frmDir):
|
||||
for dn in dirnames:
|
||||
os.chmod(os.path.join(dirpath, dn), 0775)
|
||||
os.chmod(os.path.join(dirpath, dn), STAT_0o775)
|
||||
os.chown(os.path.join(dirpath, dn), -1, gid)
|
||||
|
||||
|
||||
for fn in filenames:
|
||||
if os.path.islink(fn):
|
||||
continue
|
||||
|
@ -840,6 +943,19 @@ def buildPython():
|
|||
os.chmod(p, stat.S_IMODE(st.st_mode) | stat.S_IWGRP)
|
||||
os.chown(p, -1, gid)
|
||||
|
||||
if fn in EXPECTED_SHARED_LIBS:
|
||||
# check to see that this file was linked with the
|
||||
# expected library path and version
|
||||
data = captureCommand("otool -L %s" % shellQuote(p))
|
||||
for sl in EXPECTED_SHARED_LIBS[fn]:
|
||||
if ("\t%s " % sl) not in data:
|
||||
print("Expected shared lib %s was not linked with %s"
|
||||
% (sl, p))
|
||||
shared_lib_error = True
|
||||
|
||||
if shared_lib_error:
|
||||
fatal("Unexpected shared library errors.")
|
||||
|
||||
if PYTHON_3:
|
||||
LDVERSION=None
|
||||
VERSION=None
|
||||
|
@ -863,19 +979,26 @@ def buildPython():
|
|||
|
||||
# We added some directories to the search path during the configure
|
||||
# phase. Remove those because those directories won't be there on
|
||||
# the end-users system.
|
||||
path =os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework',
|
||||
'Versions', version, 'lib', 'python%s'%(version,),
|
||||
'config' + config_suffix, 'Makefile')
|
||||
fp = open(path, 'r')
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
# the end-users system. Also remove the directories from _sysconfigdata.py
|
||||
# (added in 3.3) if it exists.
|
||||
|
||||
data = data.replace('-L%s/libraries/usr/local/lib'%(WORKDIR,), '')
|
||||
data = data.replace('-I%s/libraries/usr/local/include'%(WORKDIR,), '')
|
||||
fp = open(path, 'w')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
path_to_lib = os.path.join(rootDir, 'Library', 'Frameworks',
|
||||
'Python.framework', 'Versions',
|
||||
version, 'lib', 'python%s'%(version,))
|
||||
paths = [os.path.join(path_to_lib, 'config' + config_suffix, 'Makefile'),
|
||||
os.path.join(path_to_lib, '_sysconfigdata.py')]
|
||||
for path in paths:
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
fp = open(path, 'r')
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
|
||||
data = data.replace(' -L%s/libraries/usr/local/lib'%(WORKDIR,), '')
|
||||
data = data.replace(' -I%s/libraries/usr/local/include'%(WORKDIR,), '')
|
||||
fp = open(path, 'w')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
|
||||
# Add symlinks in /usr/local/bin, using relative links
|
||||
usr_local_bin = os.path.join(rootDir, 'usr', 'local', 'bin')
|
||||
|
@ -907,17 +1030,17 @@ def patchFile(inPath, outPath):
|
|||
|
||||
# This one is not handy as a template variable
|
||||
data = data.replace('$PYTHONFRAMEWORKINSTALLDIR', '/Library/Frameworks/Python.framework')
|
||||
fp = open(outPath, 'wb')
|
||||
fp = open(outPath, 'w')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
|
||||
def patchScript(inPath, outPath):
|
||||
data = fileContents(inPath)
|
||||
data = data.replace('@PYVER@', getVersion())
|
||||
fp = open(outPath, 'wb')
|
||||
fp = open(outPath, 'w')
|
||||
fp.write(data)
|
||||
fp.close()
|
||||
os.chmod(outPath, 0755)
|
||||
os.chmod(outPath, STAT_0o755)
|
||||
|
||||
|
||||
|
||||
|
@ -934,7 +1057,7 @@ def packageFromRecipe(targetDir, recipe):
|
|||
readme = textwrap.dedent(recipe['readme'])
|
||||
isRequired = recipe.get('required', True)
|
||||
|
||||
print "- building package %s"%(pkgname,)
|
||||
print("- building package %s"%(pkgname,))
|
||||
|
||||
# Substitute some variables
|
||||
textvars = dict(
|
||||
|
@ -979,7 +1102,7 @@ def packageFromRecipe(targetDir, recipe):
|
|||
patchScript(postflight, os.path.join(rsrcDir, 'postflight'))
|
||||
|
||||
vers = getFullVersion()
|
||||
major, minor = map(int, getVersion().split('.', 2))
|
||||
major, minor = getVersionMajorMinor()
|
||||
pl = Plist(
|
||||
CFBundleGetInfoString="Python.%s %s"%(pkgname, vers,),
|
||||
CFBundleIdentifier='org.python.Python.%s'%(pkgname,),
|
||||
|
@ -1016,7 +1139,7 @@ def packageFromRecipe(targetDir, recipe):
|
|||
def makeMpkgPlist(path):
|
||||
|
||||
vers = getFullVersion()
|
||||
major, minor = map(int, getVersion().split('.', 2))
|
||||
major, minor = getVersionMajorMinor()
|
||||
|
||||
pl = Plist(
|
||||
CFBundleGetInfoString="Python %s"%(vers,),
|
||||
|
@ -1127,7 +1250,7 @@ def buildDMG():
|
|||
# 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/"%(
|
||||
runCommand("SetFile -a C %s/"%(
|
||||
shellQuote(os.path.join(WORKDIR, "mnt", volname)),))
|
||||
|
||||
runCommand("hdiutil detach %s"%(shellQuote(os.path.join(WORKDIR, "mnt", volname))))
|
||||
|
@ -1168,6 +1291,7 @@ def main():
|
|||
|
||||
os.environ['MACOSX_DEPLOYMENT_TARGET'] = DEPTARGET
|
||||
os.environ['CC'] = CC
|
||||
os.environ['CXX'] = CXX
|
||||
|
||||
if os.path.exists(WORKDIR):
|
||||
shutil.rmtree(WORKDIR)
|
||||
|
@ -1198,7 +1322,7 @@ def main():
|
|||
|
||||
folder = os.path.join(WORKDIR, "_root", "Applications", "Python %s"%(
|
||||
getVersion(),))
|
||||
os.chmod(folder, 0755)
|
||||
os.chmod(folder, STAT_0o755)
|
||||
setIcon(folder, "../Icons/Python Folder.icns")
|
||||
|
||||
# Create the installer
|
||||
|
@ -1211,9 +1335,9 @@ def main():
|
|||
shutil.copy('../../LICENSE', os.path.join(WORKDIR, 'installer', 'License.txt'))
|
||||
|
||||
fp = open(os.path.join(WORKDIR, 'installer', 'Build.txt'), 'w')
|
||||
print >> fp, "# BUILD INFO"
|
||||
print >> fp, "# Date:", time.ctime()
|
||||
print >> fp, "# By:", pwd.getpwuid(os.getuid()).pw_gecos
|
||||
fp.write("# BUILD INFO\n")
|
||||
fp.write("# Date: %s\n" % time.ctime())
|
||||
fp.write("# By: %s\n" % pwd.getpwuid(os.getuid()).pw_gecos)
|
||||
fp.close()
|
||||
|
||||
# And copy it to a DMG
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
diff -r -u ncurses-5.5-orig/test/Makefile.in ncurses-5.5/test/Makefile.in
|
||||
--- ncurses-5.5-orig/test/Makefile.in 2006-03-24 12:47:40.000000000 +0100
|
||||
+++ ncurses-5.5/test/Makefile.in 2006-03-24 12:47:50.000000000 +0100
|
||||
@@ -75,7 +75,7 @@
|
||||
MATH_LIB = @MATH_LIB@
|
||||
|
||||
LD = @LD@
|
||||
-LINK = @LINK_TESTS@ $(LIBTOOL_LINK) $(CC) $(CFLAGS)
|
||||
+LINK = @LINK_TESTS@ $(LIBTOOL_LINK) $(CC)
|
||||
|
||||
usFLAGS = @LD_MODEL@ @LOCAL_LDFLAGS@ @LDFLAGS@
|
||||
|
||||
diff -ru ncurses-5.5-orig/ncurses/tinfo/read_entry.c ncurses-5.5/ncurses/tinfo/read_entry.c
|
||||
--- ncurses-5.5-orig/ncurses/tinfo/read_entry.c 2004-01-11 02:57:05.000000000 +0100
|
||||
+++ ncurses-5.5/ncurses/tinfo/read_entry.c 2006-03-25 22:49:39.000000000 +0100
|
||||
@@ -474,7 +474,7 @@
|
||||
}
|
||||
|
||||
/* truncate the terminal name to prevent buffer overflow */
|
||||
- (void) sprintf(ttn, "%c/%.*s", *tn, (int) sizeof(ttn) - 3, tn);
|
||||
+ (void) sprintf(ttn, "%x/%.*s", *tn, (int) sizeof(ttn) - 3, tn);
|
||||
|
||||
/* This is System V behavior, in conjunction with our requirements for
|
||||
* writing terminfo entries.
|
||||
diff -ru ncurses-5.5-orig/configure ncurses-5.5/configure
|
||||
--- ncurses-5.5-orig/configure 2005-09-24 23:50:50.000000000 +0200
|
||||
+++ ncurses-5.5/configure 2006-03-26 22:24:59.000000000 +0200
|
||||
@@ -5027,7 +5027,7 @@
|
||||
darwin*)
|
||||
EXTRA_CFLAGS="-no-cpp-precomp"
|
||||
CC_SHARED_OPTS="-dynamic"
|
||||
- MK_SHARED_LIB='$(CC) -dynamiclib -install_name $(DESTDIR)$(libdir)/`basename $@` -compatibility_version $(ABI_VERSION) -current_version $(ABI_VERSION) -o $@'
|
||||
+ MK_SHARED_LIB='$(CC) $(CFLAGS) -dynamiclib -install_name $(DESTDIR)$(libdir)/`basename $@` -compatibility_version $(ABI_VERSION) -current_version $(ABI_VERSION) -o $@'
|
||||
test "$cf_cv_shlib_version" = auto && cf_cv_shlib_version=abi
|
||||
cf_cv_shlib_version_infix=yes
|
||||
;;
|
|
@ -5,8 +5,15 @@ $ARCHITECTURES.
|
|||
Installation requires approximately $INSTALL_SIZE MB of disk space,
|
||||
ignore the message that it will take zero bytes.
|
||||
|
||||
You must install onto your current boot disk, even though the
|
||||
installer does not enforce this, otherwise things will not work.
|
||||
If you are attempting to install on an OS X 10.8 system, you may
|
||||
see a message that Python can't be installed because it is from an
|
||||
unidentified developer. This is because this Python installer
|
||||
package is not yet compatible with the Gatekeeper security feature
|
||||
introduced in OS X 10.8. To allow Python to be installed, you
|
||||
can override the Gatekeeper policy for this install. In the Finder,
|
||||
instead of double-clicking, control-click or right click the "Python"
|
||||
installer package icon. Then select "Open using ... Installer" from
|
||||
the contextual menu that appears.
|
||||
|
||||
Python consists of the Python programming language interpreter, plus
|
||||
a set of programs to allow easy access to it for Mac users including
|
||||
|
@ -16,10 +23,11 @@ Python programs.
|
|||
|
||||
**** IMPORTANT ****
|
||||
|
||||
Before using IDLE or other programs using the tkinter graphical user
|
||||
interface toolkit, visit http://www.python.org/download/mac/tcltk/
|
||||
for current information about supported and recommended versions
|
||||
of Tcl/Tk for this version of Python and Mac OS X.
|
||||
To use IDLE or other programs that use the tkinter graphical user
|
||||
interface toolkit, you may need to install a third-party version of
|
||||
the Tcl/Tk frameworks. Visit http://www.python.org/download/mac/tcltk/
|
||||
for current information about supported and recommended versions of
|
||||
Tcl/Tk for this version of Python and of Mac OS X.
|
||||
|
||||
*******************
|
||||
|
||||
|
@ -32,5 +40,13 @@ optionally place links to the command-line tools in /usr/local/bin as
|
|||
well. Double-click on the "Update Shell Profile" command to add the
|
||||
"bin" directory inside the framework to your shell's search path.
|
||||
|
||||
You must install onto your current boot disk, even though the
|
||||
installer does not enforce this, otherwise things will not work.
|
||||
|
||||
You can verify the integrity of the disk image file containing the
|
||||
installer package and this ReadMe file by comparing its md5 checksum
|
||||
and size with the values published on the release page linked at
|
||||
http://www.python.org/download/
|
||||
|
||||
More information on Python in general can be found at
|
||||
http://www.python.org.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf470
|
||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\paperw11904\paperh16836\margl1440\margr1440\vieww9640\viewh10620\viewkind0
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural
|
||||
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640
|
||||
|
||||
\f0\fs24 \cf0 This package will install
|
||||
\b Python $FULL_VERSION
|
||||
|
@ -20,9 +20,9 @@ See the ReadMe file and the Python documentation for more information.\
|
|||
\
|
||||
|
||||
\b NOTE:
|
||||
\b0 This package will by default not update your shell profile and will also not install files in /usr/local. Double-click
|
||||
\b0 This package will not update your shell profile by default. Double-click
|
||||
\b Update Shell Profile
|
||||
\b0 at any time to make $FULL_VERSION the default Python.\
|
||||
\b0 at any time to make $FULL_VERSION the default Python 3 version. This version can co-exist with other installed versions of Python 3 and Python 2.\
|
||||
\
|
||||
|
||||
\b IMPORTANT:
|
||||
|
|
|
@ -5,19 +5,10 @@ FWK="/Library/Frameworks/Python.framework/Versions/${PYVER}"
|
|||
FWK_DOCDIR_SUBPATH="Resources/English.lproj/Documentation"
|
||||
FWK_DOCDIR="${FWK}/${FWK_DOCDIR_SUBPATH}"
|
||||
APPDIR="/Applications/Python ${PYVER}"
|
||||
DEV_DOCDIR="/Developer/Documentation"
|
||||
SHARE_DIR="${FWK}/share"
|
||||
SHARE_DOCDIR="${SHARE_DIR}/doc/python${PYVER}"
|
||||
SHARE_DOCDIR_TO_FWK="../../.."
|
||||
|
||||
# make link in /Developer/Documentation/ for Xcode users
|
||||
if [ -d "${DEV_DOCDIR}" ]; then
|
||||
if [ ! -d "${DEV_DOCDIR}/Python" ]; then
|
||||
mkdir -p "${DEV_DOCDIR}/Python"
|
||||
fi
|
||||
ln -fhs "${FWK_DOCDIR}" "${DEV_DOCDIR}/Python/Reference Documentation ${PYVER}"
|
||||
fi
|
||||
|
||||
# make link in /Applications/Python m.n/ for Finder users
|
||||
if [ -d "${APPDIR}" ]; then
|
||||
ln -fhs "${FWK_DOCDIR}/index.html" "${APPDIR}/Python Documentation.html"
|
||||
|
|
|
@ -8,14 +8,24 @@ FWK="/Library/Frameworks/Python.framework/Versions/@PYVER@"
|
|||
|
||||
"${FWK}/bin/python@PYVER@" -Wi \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-x badsyntax -x site-packages \
|
||||
-f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
|
||||
"${FWK}/lib/python${PYVER}"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi -O \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-x badsyntax -x site-packages \
|
||||
-f -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \
|
||||
"${FWK}/lib/python${PYVER}"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
"${FWK}/bin/python@PYVER@" -Wi -O \
|
||||
"${FWK}/lib/python${PYVER}/compileall.py" \
|
||||
-f -x badsyntax \
|
||||
"${FWK}/lib/python${PYVER}/site-packages"
|
||||
|
||||
chgrp -R admin "${FWK}"
|
||||
chmod -R g+w "${FWK}"
|
||||
|
||||
|
|
|
@ -40,14 +40,13 @@ INSTALL_SCRIPT= @INSTALL_SCRIPT@
|
|||
INSTALL_DATA=@INSTALL_DATA@
|
||||
LN=@LN@
|
||||
STRIPFLAG=-s
|
||||
CPMAC=/Developer/Tools/CpMac
|
||||
CPMAC=CpMac
|
||||
|
||||
APPTEMPLATE=$(srcdir)/Resources/app
|
||||
APPSUBDIRS=MacOS Resources
|
||||
APPSUBDIRS=MacOS Resources
|
||||
compileall=$(srcdir)/../Lib/compileall.py
|
||||
|
||||
installapps: install_Python install_pythonw install_PythonLauncher install_IDLE \
|
||||
checkapplepython
|
||||
installapps: install_Python install_pythonw install_PythonLauncher install_IDLE
|
||||
|
||||
install_pythonw: pythonw
|
||||
$(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)"
|
||||
|
@ -196,14 +195,6 @@ installextras: $(srcdir)/Extras.install.py
|
|||
"$(DESTDIR)$(prefix)/share/doc/python$(VERSION)/examples/Tools" ; \
|
||||
chmod -R ugo+rX,go-w "$(DESTDIR)$(prefix)/share/doc/python$(VERSION)/examples/Tools"
|
||||
|
||||
|
||||
checkapplepython: $(srcdir)/Tools/fixapplepython23.py
|
||||
@if ! $(RUNSHARED) $(BUILDPYTHON) $(srcdir)/Tools/fixapplepython23.py -n; then \
|
||||
echo "* WARNING: Apple-installed Python 2.3 will have trouble building extensions from now on."; \
|
||||
echo "* WARNING: Run $(srcdir)/Tools/fixapplepython23.py with \"sudo\" to fix this."; \
|
||||
fi
|
||||
|
||||
|
||||
clean:
|
||||
rm pythonw
|
||||
cd PythonLauncher && make clean
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
"""fixapplepython23 - Fix Apple-installed Python 2.3 (on Mac OS X 10.3)
|
||||
|
||||
Python 2.3 (and 2.3.X for X<5) have the problem that building an extension
|
||||
for a framework installation may accidentally pick up the framework
|
||||
of a newer Python, in stead of the one that was used to build the extension.
|
||||
|
||||
This script modifies the Makefile (in .../lib/python2.3/config) to use
|
||||
the newer method of linking extensions with "-undefined dynamic_lookup"
|
||||
which fixes this problem.
|
||||
|
||||
The script will first check all prerequisites, and return a zero exit
|
||||
status also when nothing needs to be fixed.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import platform
|
||||
|
||||
MAKEFILE='/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/config/Makefile'
|
||||
CHANGES=((
|
||||
'LDSHARED=\t$(CC) $(LDFLAGS) -bundle -framework $(PYTHONFRAMEWORK)\n',
|
||||
'LDSHARED=\t$(CC) $(LDFLAGS) -bundle -undefined dynamic_lookup\n'
|
||||
),(
|
||||
'BLDSHARED=\t$(CC) $(LDFLAGS) -bundle -framework $(PYTHONFRAMEWORK)\n',
|
||||
'BLDSHARED=\t$(CC) $(LDFLAGS) -bundle -undefined dynamic_lookup\n'
|
||||
),(
|
||||
'CC=\t\tgcc\n',
|
||||
'CC=\t\t/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/config/PantherPythonFix/run-gcc\n'
|
||||
),(
|
||||
'CXX=\t\tc++\n',
|
||||
'CXX=\t\t/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/config/PantherPythonFix/run-g++\n'
|
||||
))
|
||||
|
||||
GCC_SCRIPT='/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/config/PantherPythonFix/run-gcc'
|
||||
GXX_SCRIPT='/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/config/PantherPythonFix/run-g++'
|
||||
SCRIPT="""#!/bin/sh
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.3
|
||||
exec %s "${@}"
|
||||
"""
|
||||
|
||||
def findline(lines, start):
|
||||
"""return line starting with given string or -1"""
|
||||
for i in range(len(lines)):
|
||||
if lines[i][:len(start)] == start:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def fix(makefile, do_apply):
|
||||
"""Fix the Makefile, if required."""
|
||||
fixed = False
|
||||
lines = open(makefile).readlines()
|
||||
|
||||
for old, new in CHANGES:
|
||||
i = findline(lines, new)
|
||||
if i >= 0:
|
||||
# Already fixed
|
||||
continue
|
||||
i = findline(lines, old)
|
||||
if i < 0:
|
||||
print('fixapplepython23: Python installation not fixed (appears broken)')
|
||||
print('fixapplepython23: missing line:', old)
|
||||
return 2
|
||||
lines[i] = new
|
||||
fixed = True
|
||||
|
||||
if fixed:
|
||||
if do_apply:
|
||||
print('fixapplepython23: Fix to Apple-installed Python 2.3 applied')
|
||||
os.rename(makefile, makefile + '~')
|
||||
open(makefile, 'w').writelines(lines)
|
||||
return 0
|
||||
else:
|
||||
print('fixapplepython23: Fix to Apple-installed Python 2.3 should be applied')
|
||||
return 1
|
||||
else:
|
||||
print('fixapplepython23: No fix needed, appears to have been applied before')
|
||||
return 0
|
||||
|
||||
def makescript(filename, compiler):
|
||||
"""Create a wrapper script for a compiler"""
|
||||
dirname = os.path.split(filename)[0]
|
||||
if not os.access(dirname, os.X_OK):
|
||||
os.mkdir(dirname, 0o755)
|
||||
fp = open(filename, 'w')
|
||||
fp.write(SCRIPT % compiler)
|
||||
fp.close()
|
||||
os.chmod(filename, 0o755)
|
||||
print('fixapplepython23: Created', filename)
|
||||
|
||||
def main():
|
||||
# Check for -n option
|
||||
if len(sys.argv) > 1 and sys.argv[1] == '-n':
|
||||
do_apply = False
|
||||
else:
|
||||
do_apply = True
|
||||
# First check OS version
|
||||
if sys.byteorder == 'little':
|
||||
# All intel macs are fine
|
||||
print("fixapplypython23: no fix is needed on MacOSX on Intel")
|
||||
sys.exit(0)
|
||||
|
||||
osver = platform.mac_ver()
|
||||
if osver != '10.3' and os.ver < '10.3.':
|
||||
print('fixapplepython23: no fix needed on MacOSX < 10.3')
|
||||
sys.exit(0)
|
||||
|
||||
if osver >= '10.4':
|
||||
print('fixapplepython23: no fix needed on MacOSX >= 10.4')
|
||||
sys.exit(0)
|
||||
|
||||
# Test that a framework Python is indeed installed
|
||||
if not os.path.exists(MAKEFILE):
|
||||
print('fixapplepython23: Python framework does not appear to be installed (?), nothing fixed')
|
||||
sys.exit(0)
|
||||
# Check that we can actually write the file
|
||||
if do_apply and not os.access(MAKEFILE, os.W_OK):
|
||||
print('fixapplepython23: No write permission, please run with "sudo"')
|
||||
sys.exit(2)
|
||||
# Create the shell scripts
|
||||
if do_apply:
|
||||
if not os.access(GCC_SCRIPT, os.X_OK):
|
||||
makescript(GCC_SCRIPT, "gcc")
|
||||
if not os.access(GXX_SCRIPT, os.X_OK):
|
||||
makescript(GXX_SCRIPT, "g++")
|
||||
# Finally fix the makefile
|
||||
rv = fix(MAKEFILE, do_apply)
|
||||
#sys.exit(rv)
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue