diff options
Diffstat (limited to 'Mac/Tools/fixapplepython23.py')
-rw-r--r-- | Mac/Tools/fixapplepython23.py | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/Mac/Tools/fixapplepython23.py b/Mac/Tools/fixapplepython23.py new file mode 100644 index 0000000..ef352ce --- /dev/null +++ b/Mac/Tools/fixapplepython23.py @@ -0,0 +1,119 @@ +#!/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 gestalt + +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, 0755) + fp = open(filename, 'w') + fp.write(SCRIPT % compiler) + fp.close() + os.chmod(filename, 0755) + 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 gestalt.gestalt('sysv') < 0x1030: + print 'fixapplepython23: no fix needed on MacOSX < 10.3' + 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) + +if __name__ == '__main__': + main() |