Import Upstream version 2.7.18
This commit is contained in:
130
Mac/Tools/fixapplepython23.py
Executable file
130
Mac/Tools/fixapplepython23.py
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env 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()
|
||||
178
Mac/Tools/pythonw.c
Normal file
178
Mac/Tools/pythonw.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* This wrapper program executes a python executable hidden inside an
|
||||
* application bundle inside the Python framework. This is needed to run
|
||||
* GUI code: some GUI API's don't work unless the program is inside an
|
||||
* application bundle.
|
||||
*
|
||||
* This program uses posix_spawn rather than plain execv because we need
|
||||
* slightly more control over how the "real" interpreter is executed.
|
||||
*
|
||||
* On OSX 10.4 (and earlier) this falls back to using exec because the
|
||||
* posix_spawnv functions aren't available there.
|
||||
*/
|
||||
#pragma weak_import posix_spawnattr_init
|
||||
#pragma weak_import posix_spawnattr_setbinpref_np
|
||||
#pragma weak_import posix_spawnattr_setflags
|
||||
#pragma weak_import posix_spawn
|
||||
|
||||
#include <Python.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_SPAWN_H
|
||||
#include <spawn.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
extern char** environ;
|
||||
|
||||
/*
|
||||
* Locate the python framework by looking for the
|
||||
* library that contains Py_Initialize.
|
||||
*
|
||||
* In a regular framework the structure is:
|
||||
*
|
||||
* Python.framework/Versions/2.7
|
||||
* /Python
|
||||
* /Resources/Python.app/Contents/MacOS/Python
|
||||
*
|
||||
* In a virtualenv style structure the expected
|
||||
* structure is:
|
||||
*
|
||||
* ROOT
|
||||
* /bin/pythonw
|
||||
* /.Python <- the dylib
|
||||
* /.Resources/Python.app/Contents/MacOS/Python
|
||||
*
|
||||
* NOTE: virtualenv's are not an officially supported
|
||||
* feature, support for that structure is provided as
|
||||
* a convenience.
|
||||
*/
|
||||
static char* get_python_path(void)
|
||||
{
|
||||
size_t len;
|
||||
Dl_info info;
|
||||
char* end;
|
||||
char* g_path;
|
||||
|
||||
if (dladdr(Py_Initialize, &info) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(info.dli_fname);
|
||||
|
||||
g_path = malloc(len+60);
|
||||
if (g_path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(g_path, info.dli_fname);
|
||||
end = g_path + len - 1;
|
||||
while (end != g_path && *end != '/') {
|
||||
end --;
|
||||
}
|
||||
end++;
|
||||
if (*end == '.') {
|
||||
end++;
|
||||
}
|
||||
strcpy(end, "Resources/Python.app/Contents/MacOS/" PYTHONFRAMEWORK);
|
||||
|
||||
return g_path;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SPAWN_H
|
||||
static void
|
||||
setup_spawnattr(posix_spawnattr_t* spawnattr)
|
||||
{
|
||||
size_t ocount;
|
||||
size_t count;
|
||||
cpu_type_t cpu_types[1];
|
||||
short flags = 0;
|
||||
#ifdef __LP64__
|
||||
int ch;
|
||||
#endif
|
||||
|
||||
if ((errno = posix_spawnattr_init(spawnattr)) != 0) {
|
||||
err(2, "posix_spawnattr_int");
|
||||
/* NOTREACHTED */
|
||||
}
|
||||
|
||||
count = 1;
|
||||
|
||||
/* Run the real python executable using the same architecture as this
|
||||
* executable, this allows users to control the architecture using
|
||||
* "arch -ppc python"
|
||||
*/
|
||||
|
||||
#if defined(__ppc64__)
|
||||
cpu_types[0] = CPU_TYPE_POWERPC64;
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
cpu_types[0] = CPU_TYPE_X86_64;
|
||||
|
||||
#elif defined(__ppc__)
|
||||
cpu_types[0] = CPU_TYPE_POWERPC;
|
||||
#elif defined(__i386__)
|
||||
cpu_types[0] = CPU_TYPE_X86;
|
||||
#else
|
||||
# error "Unknown CPU"
|
||||
#endif
|
||||
|
||||
if (posix_spawnattr_setbinpref_np(spawnattr, count,
|
||||
cpu_types, &ocount) == -1) {
|
||||
err(1, "posix_spawnattr_setbinpref");
|
||||
/* NOTREACHTED */
|
||||
}
|
||||
if (count != ocount) {
|
||||
fprintf(stderr, "posix_spawnattr_setbinpref failed to copy\n");
|
||||
exit(1);
|
||||
/* NOTREACHTED */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set flag that causes posix_spawn to behave like execv
|
||||
*/
|
||||
flags |= POSIX_SPAWN_SETEXEC;
|
||||
if ((errno = posix_spawnattr_setflags(spawnattr, flags)) != 0) {
|
||||
err(1, "posix_spawnattr_setflags");
|
||||
/* NOTREACHTED */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
char* exec_path = get_python_path();
|
||||
|
||||
/*
|
||||
* Let argv[0] refer to the new interpreter. This is needed to
|
||||
* get the effect we want on OSX 10.5 or earlier. That is, without
|
||||
* changing argv[0] the real interpreter won't have access to
|
||||
* the Window Server.
|
||||
*/
|
||||
argv[0] = exec_path;
|
||||
|
||||
#ifdef HAVE_SPAWN_H
|
||||
|
||||
/* We're weak-linking to posix-spawnv to ensure that
|
||||
* an executable build on 10.5 can work on 10.4.
|
||||
*/
|
||||
if (posix_spawn != NULL) {
|
||||
posix_spawnattr_t spawnattr = NULL;
|
||||
|
||||
|
||||
setup_spawnattr(&spawnattr);
|
||||
posix_spawn(NULL, exec_path, NULL,
|
||||
&spawnattr, argv, environ);
|
||||
err(1, "posix_spawn: %s", exec_path);
|
||||
}
|
||||
#endif
|
||||
execve(exec_path, argv, environ);
|
||||
err(1, "execve: %s", argv[0]);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
Reference in New Issue
Block a user