summaryrefslogtreecommitdiffstats
path: root/Mac/Tools/fixapplepython23.py
blob: 6ba54019f0773e5f29bd1bc329aabf96a1e439eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/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 sys.byteorder == 'little':
        # All intel macs are fine
        print "fixapplypython23: no fix is needed on MacOSX on Intel"
        sys.exit(0)

    if gestalt.gestalt('sysv') < 0x1030:
        print 'fixapplepython23: no fix needed on MacOSX < 10.3'
        sys.exit(0)

    if gestalt.gestalt('sysv') >= 0x1040:
        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()