summaryrefslogtreecommitdiffstats
path: root/Mac
diff options
context:
space:
mode:
Diffstat (limited to 'Mac')
-rw-r--r--Mac/IDLE/Info.plist.in9
-rw-r--r--Mac/IDLE/Makefile.in9
-rw-r--r--Mac/IDLE/idlemain.py4
-rw-r--r--Mac/Makefile.in64
-rw-r--r--Mac/README25
-rw-r--r--Mac/Tools/pythonw.c140
6 files changed, 189 insertions, 62 deletions
diff --git a/Mac/IDLE/Info.plist.in b/Mac/IDLE/Info.plist.in
index 58e913c..1da402c 100644
--- a/Mac/IDLE/Info.plist.in
+++ b/Mac/IDLE/Info.plist.in
@@ -51,5 +51,14 @@
<string>%VERSION%</string>
<key>CFBundleVersion</key>
<string>%VERSION%</string>
+<!--
+ <key>LSMinimumSystemVersionByArchitecture</key>
+ <dict>
+ <key>x86_64</key>
+ <string>10.6.0</string>
+ <key>ppc64</key>
+ <string>10.6.0</string>
+ </dict>
+-->
</dict>
</plist>
diff --git a/Mac/IDLE/Makefile.in b/Mac/IDLE/Makefile.in
index 496c139..5446864 100644
--- a/Mac/IDLE/Makefile.in
+++ b/Mac/IDLE/Makefile.in
@@ -10,6 +10,8 @@ VERSION= @VERSION@
UNIVERSALSDK=@UNIVERSALSDK@
builddir= ../..
PYTHONFRAMEWORK=@PYTHONFRAMEWORK@
+LIPO_32BIT_FLAGS=@LIPO_32BIT_FLAGS@
+
RUNSHARED= @RUNSHARED@
BUILDEXE= @BUILDEXEEXT@
@@ -51,9 +53,12 @@ IDLE.app: \
--iconfile=$(srcdir)/../Icons/IDLE.icns \
--resource=$(srcdir)/../Icons/PythonSource.icns \
--resource=$(srcdir)/../Icons/PythonCompiled.icns \
- --python=$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)`test -f "$(DESTDIR)$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)-32" && echo "-32"` \
+ --python=$(prefix)/Resources/Python.app/Contents/MacOS/Python \
build
-
+ifneq ($(LIPO_32BIT_FLAGS),)
+ rm "IDLE.app/Contents/MacOS/Python"
+ lipo $(LIPO_32BIT_FLAGS) -output "IDLE.app/Contents/MacOS/Python" "$(BUILDPYTHON)"
+endif
Info.plist: $(srcdir)/Info.plist.in
sed 's/%VERSION%/'"`$(RUNSHARED) $(BUILDPYTHON) -c 'import platform; print platform.python_version()'`"'/g' < $(srcdir)/Info.plist.in > Info.plist
diff --git a/Mac/IDLE/idlemain.py b/Mac/IDLE/idlemain.py
index d6803ba..8b8beb9 100644
--- a/Mac/IDLE/idlemain.py
+++ b/Mac/IDLE/idlemain.py
@@ -48,7 +48,7 @@ os.chdir(os.path.expanduser('~/Documents'))
# the interpreter in the framework, by following the symlink
# exported in PYTHONEXECUTABLE.
pyex = os.environ['PYTHONEXECUTABLE']
-sys.executable = os.path.join(os.path.dirname(pyex), os.readlink(pyex))
+sys.executable = os.path.join(sys.prefix, 'bin', 'python%d.%d'%(sys.version_info[:2]))
# Remove any sys.path entries for the Resources dir in the IDLE.app bundle.
p = pyex.partition('.app')
@@ -68,6 +68,8 @@ for idx, value in enumerate(sys.argv):
break
# Now it is safe to import idlelib.
+from idlelib import macosxSupport
+macosxSupport._appbundle = True
from idlelib.PyShell import main
if __name__ == '__main__':
main()
diff --git a/Mac/Makefile.in b/Mac/Makefile.in
index b9fd377..8c389ed 100644
--- a/Mac/Makefile.in
+++ b/Mac/Makefile.in
@@ -15,6 +15,7 @@ LDFLAGS=@LDFLAGS@
FRAMEWORKUNIXTOOLSPREFIX=@FRAMEWORKUNIXTOOLSPREFIX@
PYTHONFRAMEWORK=@PYTHONFRAMEWORK@
PYTHONFRAMEWORKIDENTIFIER=@PYTHONFRAMEWORKIDENTIFIER@
+LIPO_32BIT_FLAGS=@LIPO_32BIT_FLAGS@
# These are normally glimpsed from the previous set
@@ -42,10 +43,8 @@ APPSUBDIRS=MacOS Resources
CACHERSRC=$(srcdir)/scripts/cachersrc.py
compileall=$(srcdir)/../Lib/compileall.py
-installapps: install_Python install_BuildApplet install_PythonLauncher \
- install_IDLE checkapplepython install_pythonw install_versionedtools
-
-installapps4way: install_Python4way install_BuildApplet install_PythonLauncher install_IDLE install_pythonw4way install_versionedtools
+installapps: install_Python install_pythonw install_BuildApplet install_PythonLauncher \
+ install_IDLE checkapplepython install_versionedtools
install_pythonw: pythonw
@@ -53,33 +52,13 @@ install_pythonw: pythonw
$(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/python$(VERSION)"
ln -sf python$(VERSION) "$(DESTDIR)$(prefix)/bin/python"
ln -sf pythonw$(VERSION) "$(DESTDIR)$(prefix)/bin/pythonw"
-
-
-# Install 3 variants of python/pythonw:
-# - 32-bit (i386 and ppc)
-# - 64-bit (x86_64 and ppc64)
-# - all (all four architectures)
-# - Make 'python' and 'pythonw' aliases for the 32-bit variant
-install_pythonw4way: pythonw-32 pythonw-64 pythonw
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw-64 "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)-64"
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw-64 "$(DESTDIR)$(prefix)/bin/python$(VERSION)-64"
- ln -sf python$(VERSION)-64 "$(DESTDIR)$(prefix)/bin/python-64"
- ln -sf pythonw$(VERSION)-64 "$(DESTDIR)$(prefix)/bin/pythonw-64"
-
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw-32 "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)-32"
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw-32 "$(DESTDIR)$(prefix)/bin/python$(VERSION)-32"
+ifneq ($(LIPO_32BIT_FLAGS),)
+ lipo $(LIPO_32BIT_FLAGS) -output $(DESTDIR)$(prefix)/bin/python$(VERSION)-32 pythonw
+ lipo $(LIPO_32BIT_FLAGS) -output $(DESTDIR)$(prefix)/bin/pythonw$(VERSION)-32 pythonw
ln -sf python$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/python-32"
ln -sf pythonw$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/pythonw-32"
+endif
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)-all"
- $(INSTALL_PROGRAM) $(STRIPFLAG) pythonw "$(DESTDIR)$(prefix)/bin/python$(VERSION)-all"
- ln -sf python$(VERSION)-all "$(DESTDIR)$(prefix)/bin/python-all"
- ln -sf pythonw$(VERSION)-all "$(DESTDIR)$(prefix)/bin/pythonw-all"
-
- ln -sf pythonw$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/pythonw$(VERSION)"
- ln -sf python$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/python$(VERSION)"
- ln -sf pythonw$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/pythonw"
- ln -sf python$(VERSION)-32 "$(DESTDIR)$(prefix)/bin/python"
#
# Install unix tools in /usr/local/bin. These are just aliases for the
@@ -97,10 +76,6 @@ installunixtools:
done
-# TODO: install symlinks for -32, -64 and -all as well
-installunixtools4way: installunixtools
-
-
#
# Like installunixtools, but only install links to the versioned binaries.
#
@@ -114,9 +89,6 @@ altinstallunixtools:
ln -fs "$(prefix)/bin/$${fn}" "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin/$${fn}" ;\
done
-# TODO: -32, -64 and -all variants
-altinstallunixtools4way: altinstallunixtools
-
# By default most tools are installed without a version in their basename, to
# make it easier to install (and use) several python versions side-by-side move
# the tools to a version-specific name and add the non-versioned name as an
@@ -141,16 +113,7 @@ install_versionedtools:
pythonw: $(srcdir)/Tools/pythonw.c Makefile
- $(CC) $(LDFLAGS) -o $@ $(srcdir)/Tools/pythonw.c \
- -DPYTHONWEXECUTABLE='"$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)"'
-
-pythonw-32: $(srcdir)/Tools/pythonw.c Makefile
- $(CC) $(LDFLAGS) -o $@ -arch i386 -arch ppc $(srcdir)/Tools/pythonw.c \
- -DPYTHONWEXECUTABLE='"$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-32"'
-
-pythonw-64: $(srcdir)/Tools/pythonw.c Makefile
- $(CC) $(LDFLAGS) -o $@ -arch x86_64 -arch ppc64 $(srcdir)/Tools/pythonw.c \
- -DPYTHONWEXECUTABLE='"$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-64"'
+ $(CC) $(LDFLAGS) -o $@ $(srcdir)/Tools/pythonw.c -I.. -I$(srcdir)/../Include ../$(PYTHONFRAMEWORK).framework/Versions/$(VERSION)/$(PYTHONFRAMEWORK)
install_PythonLauncher:
cd PythonLauncher && make install DESTDIR=$(DESTDIR)
@@ -206,11 +169,6 @@ install_Python:
> "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist"
rm "$(DESTDIR)$(APPINSTALLDIR)/Contents/Info.plist.in"
-install_Python4way: install_Python
- lipo -extract i386 -extract ppc7400 -output "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-32" "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)"
- lipo -extract x86_64 -extract ppc64 -output "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)-64" "$(DESTDIR)$(APPINSTALLDIR)/Contents/MacOS/$(PYTHONFRAMEWORK)"
-
-
install_IDLE:
cd IDLE && make install
@@ -218,9 +176,13 @@ install_IDLE:
install_BuildApplet:
$(RUNSHARED) @ARCH_RUN_32BIT@ $(BUILDPYTHON) $(srcdir)/scripts/BuildApplet.py \
--destroot "$(DESTDIR)" \
- --python=$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)`test -f "$(DESTDIR)$(prefix)/Resources/Python.app/Contents/MacOS/$(PYTHONFRAMEWORK)-32" && echo "-32"` \
+ --python=$(prefix)/Resources/Python.app/Contents/MacOS/Python \
--output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app" \
$(srcdir)/scripts/BuildApplet.py
+ifneq ($(LIPO_32BIT_FLAGS),)
+ rm "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app/Contents/MacOS/Python"
+ lipo $(LIPO_32BIT_FLAGS) -output "$(DESTDIR)$(PYTHONAPPSDIR)/Build Applet.app/Contents/MacOS/Python" $(BUILDPYTHON)
+endif
MACLIBDEST=$(LIBDEST)/plat-mac
MACTOOLSDEST=$(prefix)/Mac/Tools
diff --git a/Mac/README b/Mac/README
index c4f6b65..988e624 100644
--- a/Mac/README
+++ b/Mac/README
@@ -25,7 +25,7 @@ Mac-specific arguments to configure
Create a universal binary build of of Python. This can be used with both
regular and framework builds.
- The optional argument specifies with OSX SDK should be used to perform the
+ The optional argument specifies which OSX SDK should be used to perform the
build. This defaults to ``/Developer/SDKs/MacOSX.10.4u.sdk``, specify
``/`` when building on a 10.5 system, especially when building 64-bit code.
@@ -88,10 +88,29 @@ values are available:
* ``intel``: ``i386``, ``x86_64``
-To build a universal binary that includes a 64-bit architecture you must build
-on a system running OSX 10.5 or later. The ``all`` flavour can only be build on
+To build a universal binary that includes a 64-bit architecture, you must build
+on a system running OSX 10.5 or later. The ``all`` flavour can only be built on
OSX 10.5.
+The makefile for a framework build will install ``python32`` and ``pythonw32``
+binaries when the universal architecures includes at least one 32-bit architecture
+(that is, for all flavours but ``64-bit``).
+
+Running a specific archicture
+.............................
+
+You can run code using a specific architecture using the ``arch`` command::
+
+ $ arch -i386 python
+
+Or to explicitly run in 32-bit mode, regardless of the machine hardware::
+
+ $ arch -i386 -ppc python
+
+NOTE: When you're using a framework install of Python this requires at least
+Python 2.7 or 3.2, in earlier versions the python (and pythonw) commands are
+wrapper tools that execute the real interpreter without ensuring that the
+real interpreter runs with the same architecture.
Building and using a framework-based Python on Mac OS X.
========================================================
diff --git a/Mac/Tools/pythonw.c b/Mac/Tools/pythonw.c
index e70a76f..d7a86f2 100644
--- a/Mac/Tools/pythonw.c
+++ b/Mac/Tools/pythonw.c
@@ -3,15 +3,145 @@
* 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.
*/
#include <unistd.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
#include <err.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <Python.h>
-static char Python[] = PYTHONWEXECUTABLE;
-int main(int argc, char **argv) {
- argv[0] = Python;
- execv(Python, argv);
- err(1, "execv: %s", Python);
+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[1] == '.') {
+ end++;
+ }
+ strcpy(end, "Resources/Python.app/Contents/MacOS/Python");
+
+ return g_path;
+}
+
+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 architure as this
+ * executable, this allows users to controle 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 */
+ }
+}
+
+int
+main(int argc, char **argv) {
+ posix_spawnattr_t spawnattr = NULL;
+ char* exec_path = get_python_path();
+
+
+ setup_spawnattr(&spawnattr);
+ posix_spawn(NULL, exec_path, NULL,
+ &spawnattr, argv, environ);
+ err(1, "posix_spawn: %s", argv[0]);
/* NOTREACHED */
}