{"id":27,"date":"2011-09-05T16:11:00","date_gmt":"2011-09-05T19:11:00","guid":{"rendered":"http:\/\/mdqinc.com\/blog\/?p=27"},"modified":"2013-02-19T21:55:03","modified_gmt":"2013-02-20T00:55:03","slug":"cross-compiling-python-for-android","status":"publish","type":"post","link":"https:\/\/mdqinc.com\/blog\/2011\/09\/cross-compiling-python-for-android\/","title":{"rendered":"Cross compiling Python for Android"},"content":{"rendered":"<p>So, one day you wake up and decide that you don\u2019t have enough problems in your life and that you\u2019d like to have more. That\u2019s when you go with the obvious choice: You\u2019ll try to cross compile the Python runtime for use in Android.<\/p>\n<p>These instructions and the <a href=\"https:\/\/bitbucket.org\/gabomdq\/ignifuga\/raw\/tip\/tools\/patches\/python.android.diff\" target=\"_blank\">required patch<\/a> apply to <a href=\"http:\/\/www.python.org\/getit\/releases\/2.7.2\/\" target=\"_blank\">Python v2.7.2<\/a> (at least that\u2019s the version I know works). The patch was adapted by me, and it\u2019s based on the <a href=\"http:\/\/code.google.com\/p\/python-for-android\/source\/browse\/python-build\/Python-2.6.2-android.patch?spec=svnadbf77797fb198bd05d32cd06ac63e12f2989fec&amp;name=adbf77797f&amp;r=adbf77797fb198bd05d32cd06ac63e12f2989fec\" target=\"_blank\">Py4A patch<\/a>. I also got ideas and guidance from the <a href=\"http:\/\/pygame.renpy.org\/\" target=\"_blank\">Pygame For Android<\/a> project, specially their build scripts, which if you are interested in this kind of self inflicted pain I suggest you have a look at them. All testing and development was done on Ubuntu Natty 64 bits version.<\/p>\n<p>The first thing we have to do is create a host version of the Python runtime, as it is required to cross compile Python. This is easily done by extracting the Python source, and running the usual configure\/make\/make install.<\/p>\n<p>Once you have that, after extracting the Python source to some other place and applying <a href=\"https:\/\/bitbucket.org\/gabomdq\/ignifuga\/raw\/tip\/tools\/patches\/python.android.diff\" target=\"_blank\">the patch<\/a> (patch -p0 python-2.7.2.android.diff), you need to set up the <a href=\"http:\/\/developer.android.com\/sdk\/ndk\/index.html\" target=\"_blank\">Android NDK<\/a>, and set up some environment variables (valid at least for Android NDK R6):<\/p>\n<pre class=\"brush:bash\">export ANDROID_NDK=[PATH WHERE THE ANDROID NDK IS]\r\nexport PATH=\"$ANDROID_NDK\/toolchains\/arm-linux-androideabi-4.4.3\/prebuilt\/linux-x86\/bin\/:$ANDROID_NDK:$ANDROID_NDK\/tools:\/usr\/local\/bin:\/usr\/bin:\/bin\"\r\nexport ARCH=\"armeabi\"\r\nexport CFLAGS=\"-DANDROID -mandroid -fomit-frame-pointer --sysroot $ANDROID_NDK\/platforms\/android-5\/arch-arm\"\r\nexport CXXFLAGS = \"$CFLAGS\"\r\nexport CC=\"arm-linux-androideabi-gcc $CFLAGS\"\r\nexport CXX=\"arm-linux-androideabi-g++ $CXXFLAGS\"\r\nexport AR=\"arm-linux-androideabi-ar\"\r\nexport RANLIB=\"arm-linux-androideabi-ranlib\"\r\nexport STRIP=\"arm-linux-androideabi-strip --strip-unneeded\"\r\nexport MAKE=\"make -j4 HOSTPYTHON=[PATH TO HOST PYTHON] HOSTPGEN=[PATH TO HOST PGEN] CROSS_COMPILE=arm-eabi- CROSS_COMPILE_TARGET=yes\"<\/pre>\n<p>In the final variable \u201cMAKE\u201d up above you have to complete the appropriate full path to the python executable and pgen executable that you generated when you compiled Python for the host (I don\u2019t go into the details of compiling Python for the host as it is rather simple and there\u2019s plenty of information on the net about this, as I mentioned it shouldn\u2019t be harder than doing configure\/make\/make install).<\/p>\n<p>I configured the cross compilation with:<\/p>\n<pre class=\"brush:bash\">.\/configure LDFLAGS=\"-Wl,--allow-shlib-undefined\" CFLAGS=\"-mandroid -fomit-frame-pointer --sysroot $ANDROID_NDK\/platforms\/android-5\/arch-arm\" HOSTPYTHON=[HOST PYTHON PATH] HOSTPGEN=[HOST PGEN PATH] --host=arm-eabi --build=i686-pc-linux-gnu --enable-shared --prefix=\"[WHERE YOU WANT TO PUT THE GENERATED PYTHON STUFF]\"<\/pre>\n<p>After this I had to make a small correction to the generated Makefile.<\/p>\n<pre class=\"brush:bash\">sed -i \"s|^INSTSONAME=\\(.*.so\\).*|INSTSONAME=\\\\1|g\" Makefile<\/pre>\n<p>Now you are ready to compile:<\/p>\n<pre class=\"brush:bash\">$MAKE<\/pre>\n<p>With a little bit of luck that should be it, I promised pain but it didn\u2019t seem like much trouble, right? Well, I just gave you my hard earned patch that makes the trick!<\/p>\n<p>Actually using the compiled library is a different matter entirely, but to give you a hint of where to go I suggest that you take a look at my previous article on how to embed and freeze modules and packages in Python, which is what I did. Once you do that, maybe mix it with a bit of SDL (of special interest is the Android project skeleton that they use), and you\u2019ll have a fully working Python environment that you can build apps on!<\/p>\n<p>Stay tuned for instructions on how to accomplish something similar (but with a WAY bigger patch) for cross compiling to Windows via Mingw32<\/p>\n<p>UPDATE: Thanks to Anthony Prieur who let me know of a couple of typos in the instructions (already fixed) and that the patch has an indentation issue in setup.py, which is trivial to fix if you need the file (I don\u2019t have any use for that file in the application I\u2019m developing).<br \/>\nUPDATE2: Patch now supports cross compiling from OS X in addition to Linux.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So, one day you wake up and decide that you don\u2019t have enough problems in your life and that you\u2019d like to have more. That\u2019s when you go with the obvious choice: You\u2019ll try to cross compile the Python runtime for use in Android. These instructions and the required patch apply to Python v2.7.2 (at [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,3,4],"tags":[],"_links":{"self":[{"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/posts\/27"}],"collection":[{"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":6,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":67,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/posts\/27\/revisions\/67"}],"wp:attachment":[{"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mdqinc.com\/blog\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}