Cross compiling Python for Android

Sep
2011
05

Android, Programming, Python

24 comments

So, one day you wake up and decide that you don’t have enough problems in your life and that you’d like to have more. That’s when you go with the obvious choice: You’ll try to cross compile the Python runtime for use in Android.

These instructions and the required patch apply to Python v2.7.2 (at least that’s the version I know works). The patch was adapted by me, and it’s based on the Py4A patch. I also got ideas and guidance from the Pygame For Android 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.

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.

Once you have that, after extracting the Python source to some other place and applying the patch (patch -p0 python-2.7.2.android.diff), you need to set up the Android NDK, and set up some environment variables (valid at least for Android NDK R6):

export ANDROID_NDK=[PATH WHERE THE ANDROID NDK IS]
export 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"
export ARCH="armeabi"
export CFLAGS="-DANDROID -mandroid -fomit-frame-pointer --sysroot $ANDROID_NDK/platforms/android-5/arch-arm"
export CXXFLAGS = "$CFLAGS"
export CC="arm-linux-androideabi-gcc $CFLAGS"
export CXX="arm-linux-androideabi-g++ $CXXFLAGS"
export AR="arm-linux-androideabi-ar"
export RANLIB="arm-linux-androideabi-ranlib"
export STRIP="arm-linux-androideabi-strip --strip-unneeded"
export MAKE="make -j4 HOSTPYTHON=[PATH TO HOST PYTHON] HOSTPGEN=[PATH TO HOST PGEN] CROSS_COMPILE=arm-eabi- CROSS_COMPILE_TARGET=yes"

In the final variable “MAKE” 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’t go into the details of compiling Python for the host as it is rather simple and there’s plenty of information on the net about this, as I mentioned it shouldn’t be harder than doing configure/make/make install).

I configured the cross compilation with:

./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]"

After this I had to make a small correction to the generated Makefile.

sed -i "s|^INSTSONAME=\(.*.so\).*|INSTSONAME=\\1|g" Makefile

Now you are ready to compile:

$MAKE

With a little bit of luck that should be it, I promised pain but it didn’t seem like much trouble, right? Well, I just gave you my hard earned patch that makes the trick!

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’ll have a fully working Python environment that you can build apps on!

Stay tuned for instructions on how to accomplish something similar (but with a WAY bigger patch) for cross compiling to Windows via Mingw32

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’t have any use for that file in the application I’m developing).
UPDATE2: Patch now supports cross compiling from OS X in addition to Linux.