├── .gitignore ├── Python-2.6.5-xcompile.patch ├── README └── iOS-build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | Python-2.6.5 2 | Python-2.6.5.tar.bz2 3 | *~ 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /Python-2.6.5-xcompile.patch: -------------------------------------------------------------------------------- 1 | diff -uN Python-2.6.2/configure Python-2.6.2POld/configure 2 | --- Python-2.6.2/configure 2009-03-31 03:56:14.000000000 +1000 3 | 4 | @@ -24326,14 +24326,14 @@ 5 | 6 | { echo "$as_me:$LINENO: checking for %zd printf() format support" >&5 7 | echo $ECHO_N "checking for %zd printf() format support... $ECHO_C" >&6; } 8 | -if test "$cross_compiling" = yes; then 9 | - { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling 10 | -See \`config.log' for more details." >&5 11 | -echo "$as_me: error: cannot run test program while cross compiling 12 | -See \`config.log' for more details." >&2;} 13 | - { (exit 1); exit 1; }; } 14 | -else 15 | - cat >conftest.$ac_ext <<_ACEOF 16 | +#if test "$cross_compiling" = yes; then 17 | +# { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling 18 | +#See \`config.log' for more details." >&5 19 | +#echo "$as_me: error: cannot run test program while cross compiling 20 | +#See \`config.log' for more details." >&2;} 21 | +# { (exit 1); exit 1; }; } 22 | +#else 23 | +cat >conftest.$ac_ext <<_ACEOF 24 | /* confdefs.h. */ 25 | _ACEOF 26 | cat confdefs.h >>conftest.$ac_ext 27 | @@ -24411,7 +24411,7 @@ 28 | echo "${ECHO_T}no" >&6; } 29 | fi 30 | rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext 31 | -fi 32 | +#fi 33 | 34 | 35 | 36 | diff -uN Python-2.6.2/configure.in Python-2.6.2POld/configure.in 37 | --- Python-2.6.2/configure.in 2009-03-31 03:56:14.000000000 +1000 38 | +++ Python-2.6.2POld/configure.in 2009-08-17 12:19:15.000000000 +1000 39 | @@ -3656,48 +3656,48 @@ 40 | AC_MSG_RESULT(no) 41 | fi 42 | 43 | -AC_MSG_CHECKING(for %zd printf() format support) 44 | -AC_TRY_RUN([#include 45 | -#include 46 | -#include 47 | - 48 | -#ifdef HAVE_SYS_TYPES_H 49 | -#include 50 | -#endif 51 | - 52 | -#ifdef HAVE_SSIZE_T 53 | -typedef ssize_t Py_ssize_t; 54 | -#elif SIZEOF_VOID_P == SIZEOF_LONG 55 | -typedef long Py_ssize_t; 56 | -#else 57 | -typedef int Py_ssize_t; 58 | -#endif 59 | - 60 | -int main() 61 | -{ 62 | - char buffer[256]; 63 | - 64 | - if(sprintf(buffer, "%zd", (size_t)123) < 0) 65 | - return 1; 66 | - 67 | - if (strcmp(buffer, "123")) 68 | - return 1; 69 | - 70 | - if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0) 71 | - return 1; 72 | - 73 | - if (strcmp(buffer, "-123")) 74 | - return 1; 75 | - 76 | - return 0; 77 | -}], 78 | -[AC_MSG_RESULT(yes) 79 | - AC_DEFINE(PY_FORMAT_SIZE_T, "z", [Define to printf format modifier for Py_ssize_t])], 80 | - AC_MSG_RESULT(no)) 81 | +#AC_MSG_CHECKING(for %zd printf() format support) 82 | +#AC_TRY_RUN([#include 83 | +##include 84 | +##include 85 | + 86 | +##ifdef HAVE_SYS_TYPES_H 87 | +##include 88 | +##endif 89 | + 90 | +##ifdef HAVE_SSIZE_T 91 | +#typedef ssize_t Py_ssize_t; 92 | +##elif SIZEOF_VOID_P == SIZEOF_LONG 93 | +#typedef long Py_ssize_t; 94 | +##else 95 | +#typedef int Py_ssize_t; 96 | +##endif 97 | +# 98 | +#int main() 99 | +#{ 100 | +# char buffer[256]; 101 | +# 102 | +# if(sprintf(buffer, "%zd", (size_t)123) < 0) 103 | +# return 1;# 104 | +# 105 | +# if (strcmp(buffer, "123")) 106 | +# return 1; 107 | +# 108 | +# if (sprintf(buffer, "%zd", (Py_ssize_t)-123) < 0) 109 | +# return 1; 110 | +# 111 | +# if (strcmp(buffer, "-123")) 112 | +# return 1; 113 | +# 114 | +# return 0; 115 | +#}], 116 | +#[AC_MSG_RESULT(yes) 117 | +# AC_DEFINE(PY_FORMAT_SIZE_T, "z", [Define to printf format modifier for Py_ssize_t])], 118 | +# AC_MSG_RESULT(no)) 119 | 120 | AC_CHECK_TYPE(socklen_t,, 121 | AC_DEFINE(socklen_t,int, 122 | - Define to `int' if does not define.),[ 123 | + Define to 'int' if does not define.),[ 124 | #ifdef HAVE_SYS_TYPES_H 125 | #include 126 | #endif 127 | diff -uN Python-2.6.2/Makefile.pre.in Python-2.6.2POld/Makefile.pre.in 128 | --- Python-2.6.2/Makefile.pre.in 2009-02-24 21:07:44.000000000 +1000 129 | +++ Python-2.6.2POld/Makefile.pre.in 2009-08-17 12:19:15.000000000 +1000 130 | @@ -175,6 +175,7 @@ 131 | 132 | PYTHON= python$(EXE) 133 | BUILDPYTHON= python$(BUILDEXE) 134 | +HOSTPYTHON= ./$(BUILDPYTHON) 135 | 136 | # The task to run while instrument when building the profile-opt target 137 | PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck 138 | @@ -206,6 +207,8 @@ 139 | # Parser 140 | PGEN= Parser/pgen$(EXE) 141 | 142 | +HOSTPGEN= $(PGEN) 143 | + 144 | POBJS= \ 145 | Parser/acceler.o \ 146 | Parser/grammar1.o \ 147 | @@ -394,8 +397,8 @@ 148 | # Build the shared modules 149 | sharedmods: $(BUILDPYTHON) 150 | @case $$MAKEFLAGS in \ 151 | - *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \ 152 | - *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \ 153 | + *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' $(HOSTPYTHON) -E $(srcdir)/setup.py -q build;; \ 154 | + *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' $(HOSTPYTHON) -E $(srcdir)/setup.py build;; \ 155 | esac 156 | 157 | # Build static library 158 | @@ -517,7 +520,7 @@ 159 | 160 | $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) 161 | -@$(INSTALL) -d Include 162 | - -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) 163 | + -$(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) 164 | 165 | $(PGEN): $(PGENOBJS) 166 | $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) 167 | @@ -886,24 +889,24 @@ 168 | done; \ 169 | done 170 | $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt 171 | - PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 172 | - ./$(BUILDPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ 173 | + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 174 | + $(HOSTPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ 175 | -d $(LIBDEST) -f \ 176 | -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST) 177 | - PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 178 | - ./$(BUILDPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ 179 | + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 180 | + $(HOSTPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ 181 | -d $(LIBDEST) -f \ 182 | -x 'bad_coding|badsyntax|site-packages' $(DESTDIR)$(LIBDEST) 183 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 184 | - ./$(BUILDPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ 185 | + $(HOSTPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ 186 | -d $(LIBDEST)/site-packages -f \ 187 | -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages 188 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 189 | - ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ 190 | + $(HOSTPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ 191 | -d $(LIBDEST)/site-packages -f \ 192 | -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages 193 | -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ 194 | - ./$(BUILDPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" 195 | + $(HOSTPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" 196 | 197 | # Create the PLATDIR source directory, if one wasn't distributed.. 198 | $(srcdir)/Lib/$(PLATDIR): 199 | @@ -1001,7 +1004,8 @@ 200 | # Install the dynamically loadable modules 201 | # This goes into $(exec_prefix) 202 | sharedinstall: 203 | - $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \ 204 | + CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' CROSS_COMPILE='$(CROSS_COMPILE)' \ 205 | + $(RUNSHARED) $(HOSTPYTHON) -E $(srcdir)/setup.py install \ 206 | --prefix=$(prefix) \ 207 | --install-scripts=$(BINDIR) \ 208 | --install-platlib=$(DESTSHARED) \ 209 | diff -uN Python-2.6.2/setup.py Python-2.6.2POld/setup.py 210 | --- Python-2.6.2/setup.py 2009-04-01 04:20:48.000000000 +1000 211 | +++ Python-2.6.2POld/setup.py 2009-08-17 12:19:15.000000000 +1000 212 | @@ -17,7 +17,7 @@ 213 | from distutils.command.install_lib import install_lib 214 | 215 | # This global variable is used to hold the list of modules to be disabled. 216 | -disabled_module_list = [] 217 | +disabled_module_list = ['_ctypes'] 218 | 219 | def add_dir_to_list(dirlist, dir): 220 | """Add the directory 'dir' to the list 'dirlist' (at the front) if 221 | @@ -267,33 +267,40 @@ 222 | self.announce('WARNING: skipping import check for Cygwin-based "%s"' 223 | % ext.name) 224 | return 225 | + if os.environ.get('CROSS_COMPILE_TARGET') == 'yes': 226 | + return 227 | + 228 | ext_filename = os.path.join( 229 | self.build_lib, 230 | self.get_ext_filename(self.get_ext_fullname(ext.name))) 231 | try: 232 | imp.load_dynamic(ext.name, ext_filename) 233 | except ImportError, why: 234 | - self.failed.append(ext.name) 235 | - self.announce('*** WARNING: renaming "%s" since importing it' 236 | - ' failed: %s' % (ext.name, why), level=3) 237 | - assert not self.inplace 238 | - basename, tail = os.path.splitext(ext_filename) 239 | - newname = basename + "_failed" + tail 240 | - if os.path.exists(newname): 241 | - os.remove(newname) 242 | - os.rename(ext_filename, newname) 243 | - 244 | - # XXX -- This relies on a Vile HACK in 245 | - # distutils.command.build_ext.build_extension(). The 246 | - # _built_objects attribute is stored there strictly for 247 | - # use here. 248 | - # If there is a failure, _built_objects may not be there, 249 | - # so catch the AttributeError and move on. 250 | - try: 251 | - for filename in self._built_objects: 252 | - os.remove(filename) 253 | - except AttributeError: 254 | - self.announce('unable to remove files (ignored)') 255 | + if os.environ.get('CROSS_COMPILE_TARGET') != "yes": 256 | + self.announce('*** WARNING: renaming "%s" since importing it' 257 | + ' failed: %s' % (ext.name, why), level=3) 258 | + assert not self.inplace 259 | + basename, tail = os.path.splitext(ext_filename) 260 | + newname = basename + "_failed" + tail 261 | + if os.path.exists(newname): 262 | + os.remove(newname) 263 | + os.rename(ext_filename, newname) 264 | + 265 | + # XXX -- This relies on a Vile HACK in 266 | + # distutils.command.build_ext.build_extension(). The 267 | + # _built_objects attribute is stored there strictly for 268 | + # use here. 269 | + # If there is a failure, _built_objects may not be there, 270 | + # so catch the AttributeError and move on. 271 | + try: 272 | + for filename in self._built_objects: 273 | + os.remove(filename) 274 | + except AttributeError: 275 | + self.announce('unable to remove files (ignored)') 276 | + else: 277 | + self.announce('WARNING: "%s" failed importing, but we leave it ' 278 | + 'because we are cross-compiling' % 279 | + ext.name) 280 | except: 281 | exc_type, why, tb = sys.exc_info() 282 | self.announce('*** WARNING: importing extension "%s" ' 283 | @@ -665,7 +672,7 @@ 284 | 285 | if (ssl_incs is not None and 286 | ssl_libs is not None and 287 | - openssl_ver >= 0x00907000): 288 | + openssl_ver >= 0x00907000 and False): 289 | # The _hashlib module wraps optimized implementations 290 | # of hash functions from the OpenSSL library. 291 | exts.append( Extension('_hashlib', ['_hashopenssl.c'], 292 | @@ -685,7 +692,7 @@ 293 | depends = ['md5.h']) ) 294 | missing.append('_hashlib') 295 | 296 | - if (openssl_ver < 0x00908000): 297 | + if (True or openssl_ver < 0x00908000): 298 | # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash 299 | exts.append( Extension('_sha256', ['sha256module.c']) ) 300 | exts.append( Extension('_sha512', ['sha512module.c']) ) 301 | 302 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Simple script to fetch, patch and build python for the iPhone and 2 | iPhone Simulator 3 | 4 | IMPORTANT NOTE: 5 | This project never really got python running on the iPhone to my satisfaction, 6 | and I can't recommend using it for any serious project at this stage. 7 | 8 | Most notably missing is pyobjc support (which turns out to be much harder to 9 | port to iPhone since it relies on more platform-specific code) 10 | 11 | Also missing is the ability to statically compile modules, (all are currently 12 | built as dylibs which works for development, but to my knowledge wouldn't be 13 | allowed in the App Store) 14 | 15 | At this point this project is mostly meant to be a starting point for anyone 16 | smarter than me who wants to and can tackle the above issues. 17 | 18 | I really wish it were practical to write apps entirely in Python, but at this 19 | point it seems impossible. 20 | 21 | Last known to work on Xcode 4.3.2 SDK 5.1 (works on my machine anyway) 22 | 23 | The final products are located in `Python-2.6.5/_install/' 24 | 25 | the most interesting files for iPhone development being 26 | * include/ 27 | * lib/libpython2.6.a 28 | * lib/python2.6/ 29 | 30 | To compile with Xcode, add libpython2.6.a to your project and copy the 31 | directory `lib' into your resources folder. You will also need to add 32 | `include' to your header search path. 33 | 34 | Known bug: 35 | * spaces cannot be present in path (most likely an issue with the Python Makefile) 36 | 37 | 38 | -------------------------------------------------------------------------------- /iOS-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | set -o errexit 3 | 4 | # credit to: 5 | # http://randomsplat.com/id5-cross-compiling-python-for-embedded-linux.html 6 | # http://latenitesoft.blogspot.com/2008/10/iphone-programming-tips-building-unix.html 7 | 8 | export MIN_IOS_VERSION=5.0 9 | 10 | # download python if it isn't there 11 | if [[ ! -a Python-2.6.5.tar.bz2 ]]; then 12 | curl http://www.python.org/ftp/python/2.6.5/Python-2.6.5.tar.bz2 > Python-2.6.5.tar.bz2 13 | fi 14 | 15 | # get rid of old build 16 | rm -rf Python-2.6.5 17 | 18 | # build for native machine 19 | tar -xjf Python-2.6.5.tar.bz2 20 | pushd ./Python-2.6.5 21 | 22 | ./configure CC="xcrun clang" 23 | xcrun make -j 3 python.exe Parser/pgen 24 | 25 | mv python.exe hostpython 26 | mv Parser/pgen Parser/hostpgen 27 | 28 | xcrun make distclean 29 | 30 | # patch python to cross-compile 31 | patch -p1 < ../Python-2.6.5-xcompile.patch 32 | 33 | # set up environment variables for simulator compilation 34 | export SDK="iphonesimulator" 35 | export SDKROOT=$(xcodebuild -version -sdk "$SDK" Path) 36 | export IOS_COMPILER=$(xcrun -find -sdk "$SDK" llvm-gcc) 37 | export LD=$(xcrun -find -sdk "$SDK" ld) 38 | 39 | export CFLAGS="-m32 -isysroot $SDKROOT -miphoneos-version-min=$MIN_IOS_VERSION" 40 | export LDFLAGS="-isysroot $SDKROOT -static-libgcc -miphoneos-version-min=$MIN_IOS_VERSION" 41 | export CPP=$(xcrun -find -sdk "$SDK" cpp) 42 | 43 | # build for iPhone Simulator 44 | ./configure CC="$IOS_COMPILER $CFLAGS" \ 45 | --disable-toolbox-glue \ 46 | --host=i386-apple-darwin 47 | 48 | xcrun make -j 3 HOSTPYTHON=./hostpython HOSTPGEN=./Parser/hostpgen \ 49 | CROSS_COMPILE_TARGET=yes 50 | 51 | mv libpython2.6.a libpython2.6-i386.a 52 | 53 | xcrun make distclean 54 | 55 | # set up environment variables for cross compilation 56 | export SDK="iphoneos" 57 | export SDKROOT=$(xcodebuild -version -sdk "$SDK" Path) 58 | export IOS_COMPILER=$(xcrun -find -sdk "$SDK" llvm-gcc) 59 | export LD=$(xcrun -find -sdk "$SDK" ld) 60 | 61 | if [ ! -d "$SDKROOT" ]; then 62 | echo "SDKROOT doesn't exist. SDKROOT=$SDKROOT" 63 | exit 1 64 | fi 65 | 66 | if [ ! -f "$IOS_COMPILER" ]; then 67 | echo "Error: compiler not found at $IOS_COMPILER" 68 | exit 1 69 | fi 70 | 71 | export CFLAGS="-isysroot $SDKROOT -miphoneos-version-min=$MIN_IOS_VERSION -arch armv7" 72 | export LDFLAGS="-isysroot $SDKROOT -static-libgcc -miphoneos-version-min=$MIN_IOS_VERSION -arch armv7" 73 | export CPP=$(xcrun -find -sdk "$SDK" cpp) 74 | 75 | # build for iPhone 76 | ./configure CC="$IOS_COMPILER $CFLAGS" \ 77 | --disable-toolbox-glue \ 78 | --host=arm-apple-darwin 79 | 80 | make -j 3 HOSTPYTHON=./hostpython HOSTPGEN=./Parser/hostpgen \ 81 | CROSS_COMPILE_TARGET=yes 82 | 83 | make install HOSTPYTHON=./hostpython CROSS_COMPILE_TARGET=yes prefix="$PWD/_install" 84 | 85 | pushd _install/lib 86 | mv libpython2.6.a libpython2.6-arm.a 87 | lipo -create -output libpython2.6.a ../../libpython2.6-i386.a libpython2.6-arm.a 88 | --------------------------------------------------------------------------------