Patches to get cross compilation and unit tests running for Python 3.4 for Android x86. (Should also work for Android ARM, but I haven't tested.)
Here's how to get Python 3.4.2 cross-compiled and running on Android. I am targetting Android 4.4.2 (KitKat) running 32-bit on an Intel Core i5-4250U.
My build machine is Linux (Ubuntu 14.04.1 LTS on an x86_64 machine). Any Linux with glibc 2.7 or later should work (Debian 5+, Ubuntu 8.04+, SLES 11+, Fedora 8+, RHEL 6+, Centos 6+), but I haven’t tested with anything other than Ubuntu 14.04.
I have Android SDK and Android NDK installed. NDK revision 9 or 10d. Build
the standalone toolchain for Android NDK by running
make-standalone-toolchain.sh with the appropriate args as described
at: http://www.kandroid.org/ndk/docs/STANDALONE-TOOLCHAIN.html. For example,
$ ./android-ndk-r10d-linux-x86_64.bin
$ cd android-ndk-r10d
$ build/tools/make-standalone-toolchain.sh --platform=android-19 --arch=x86 --toolchain=x86-4.9 --install-dir=/where/you/install/crosscompilers/i686-linux-android
# (or for Arm you might choose: build/tools/make-standalone-toolchain.sh --platform=android-19 --arch=arm --toolchain=arm-linux-androideabi-4.9 --install-dir=/where/you/install/crosscompilers/arm-linux-android)
The bin/ subdir of the standalone toolchain should be on your path.
The Android sdk adb tool should be on your path. (This is usually
found in the sdk/platform-tools/ subdirectory of the SDK).
Download https://www.python.org/ftp/python/3.4.2/Python-3.4.2.tar.xz and untar it.
You need a recent version of Python 3 running on the Build machine. The easiest way to do this is by compiling and installing a local version of the same Python you are trying to compile for Android.
mkdir build-buildcd build-build../Python-3.4.2/configure --enable-shared --prefix=</absolute/path/to/writable/install-dir>makemake install- Add
</absolute/path/to/writable/install-dir>/binto the front of yourPATH - Add
</absolute/path/to/writable/install-dir>/libto the front of yourLD_LIBRARY_PATH
The android-python-3.4.2.patch included in this directory is a combination of the following:
-
http://bugs.python.org/file37930/pw_gecos-field-workaround-with-config_ac-mods.patch from issue 20306.
-
http://bugs.python.org/file37042/time_select_audioop_ctypes_test_link_with_libm.patch from issue 21668.
-
http://bugs.python.org/file27898/issue16353.diff from issue 16353.
-
http://bugs.python.org/file37139/popen-no-hardcode-bin-sh.patch from issue 16255.
-
A variety of patches to attack the issues with locales/langinfo and wide chars described in issues 22747 and 20305.
Additionally if you are trying to get Python-3.5 working then you'll also need to apply:
- http://bugs.python.org/file36902/makefile-regen-fix.patch from Issue22625. (This fixes a bug with cross compilation that was introduced after Python 3.4.2 released.)
So download
android-python-3.4.2.patch into the source directory
and apply it as follows:
patch -p1 < android-python-3.4.2.patchautoheaderautoconf
(The autoheader and autoconf commands rebuild the pyconfig.h.in
file and the configure script. This is necessary because the patch
modifies configure.ac. You get these by installing the autoconf
package. apt-get install autoconf on Ubuntu/Debian, yum install autoconf on CentOS/Fedora/Red Hat).
In the directory that contains the Python-3.4.2 source tree do the
following:
-
mkdir build-for-android -
cd build-for-android -
CPPFLAGS=-I/absolute/path/to/../Python-3.4.2/FIXLOCALE ../Python-3.4.2/configure --enable-shared --prefix=/absolute/path/to/install/directory --build=x86_64-linux-gnu --host=i686-linux-android --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no ac_cv_little_endian_double=yes --without-ensurepip
(Explanation:
-
CPPFLAGSsets the include path to some .h files needed by the patch. -
../Python-3.4.2/configureis the script you're running. -
--enable-sharedtellsconfigureyou want to use shared libraries rather than static linking. -
--prefixis the path where the installation files will be placed on your build machine. If you have root access on the build machine then you probably want this to be something like/data/python-3.4.2. (In which case you shouldsudo mkdir /dataandsudo chmod go+rwx /data.) -
--buildis the system you're building on (usuallyx86_64-linux-gnu). -
--hostis the Android system you're targeting. I've goti686-linux-android, but if you're targeting an Arm based phone/tablet then this needs to be something likearm-linux-android. -
--disable-ipv6is because I couldn't get the ipv6 support to compile. -
ac_cv_file__dev_ptmxandac_cv_file__dev_ptcare to turn off some other feature that wouldn't properly cross compile. -
ac_cv_little_endian_double=yesis necessary on Android x86. I don't know about Arm. I'd start without it, and add it if any of the floating point unit tests are failing. -
--without-ensure-pipturns off some test that always fails if you're cross compiling.
-
download the patch
after-config.patchinto thebuild-for-androiddirectory. -
In the
build-for-androiddirectory runpatch -p1 < after-config.patch.
(This patch is a complete hack to deal with some more cross-compilation bugs which I haven't had time to make real patches for.)
make && make install
There may be some warnings, but there shouldn't be any errors.
How you've got your Android test box connected may be different than mine. I have the Android test box connected on my local intranet, getting an IP address from the local DHCP server.
cd \datatar --bzip2 --create --file=py.tar.bz2 python-3.4.2/adb connect <ip.address.of.android.box>adb push py.tar.bz2 /data/
Now get a shell running on the Android machine. You can do this from
a developer-enabled Android phone/tablet by running the shell
program. I prefer to do it by running adb shell from my Linux
machine (where I have a much better keyboard and monitor.)
At the Android shell prompt:
PATH=/system/xbin/busybox:$PATH:/data/python-3.4.2/binLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/python-3.4.2/libcd /data/tar xf py.tar.bz2
The LD_LIBRARY_PATH setting actually isn't required if you did your
build into --prefix=/data/python-3.4.2, but is required otherwise.
To see whether the most basic stuff is working type python3 to bring
up the interactive Python prompt. Once that is good then run python3 -m test -x test_ctypes test_threading. (test_ctypes and
test_threading are failing catastrophically at the moment.)
This should take about 10 minutes and end with something like the following:
327 tests OK.
21 tests failed:
test_asyncio test_bytes test_capi test_concurrent_futures
test_datetime test_distutils test_faulthandler test_fork1
test_inspect test_io test_mmap test_multiprocessing_main_handling
test_os test_posix test_posixpath test_pwd test_shutil test_socket
test_subprocess test_sys test_unicode
38 tests skipped:
test_bz2 test_crypt test_curses test_dbm_gnu test_dbm_ndbm
test_devpoll test_gdb test_grp test_idle test_ioctl test_kqueue
test_lzma test_msilib test_nis test_openpty test_ossaudiodev
test_pep277 test_pty test_readline test_smtpnet test_socketserver
test_spwd test_sqlite test_ssl test_startfile test_tcl
test_timeout test_tk test_ttk_guionly test_ttk_textonly
test_unicode_file test_urllib2net test_urllibnet test_wait4
test_winreg test_winsound test_xmlrpc_net test_zipfile64
If you have any ideas about why the failing tests are failing we'd love to hear from you!