转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=1474

本文的目的不是为了完整地把Python 3.2移植到Android,只是希望编译出能用在自己程序里的链接库。

完成boost 1.47的移植之后,下一个目标就是Python 3.2。目前Python只有2.6.2非官方地移植到了Android(见P4A),他们迟迟不开始移植3.x,主要原因是他们认为3.x没用-_-。看来这件事情只能自己做了。由于Python 3.x和之前的版本有着巨大的区别,其难度完全不可预测。

准备工作

需要下载

configure

按照linux平台的老习惯,很多配置是写在.in文件中,需要用configure来生成出对应的.c或者.h。这里需要特别注意的是,需要让configure用NDK的工具链:

./configure –host=arm-linux-androideabi CC=arm-linux-androideabi-gcc CPPFLAGS=”-I$ANDROID_NDK/platforms/android-9/arch-arm/usr/include -I$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/include -I$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/armeabi/include -I$ANDROID_NDK/sources/crystax/include” CFLAGS=”-nostdlib” LDFLAGS=”-Wl,-rpath-link=$ANDROID_NDK/platforms/android-9/arch-arm/usr/lib -L$ANDROID_NDK/platforms/android-9/arch-arm/usr/lib” LIBS=”-lc”

其中$ANDROID_NDK是环境变量,指向NDK的根目录。

经过configure,pyconfig.h、config.c等文件被生成出来了。需要手工把pyconfig.h拷贝到Include目录下。

工程文件

和boost不一样的是,python没有自带bjam这样的编译工具,所以得自己建立一个Android.mk。我拿了P4A的Android.mk进行一番修改,加入3.2新增的一些.c文件。

打补丁

P4A提供了一个Python-2.6.2-android.patch,但仅仅适用于2.6.2,毕竟3.x和2.x差异太大了。这里需要修改Python 3.2的源代码,手工把一个个补丁打上。注意pyconfig.h和config.c就不用改了。

编译

ndk-build进行编译,刚开始一切顺利,接着问题出现。首先出现编译错误的是Objects/unicodeobject.c。在有wchar的情况下,它需要有PY_FORMAT_LONG_LONG的定义。但不知为何,configure并没有生成正确的PY_FORMAT_LONG_LONG。于是我加上了一行

1
#define PY_FORMAT_LONG_LONG "ll"

接着Modules/posixmodule.c编译错误。经过细致的检查,我发现是因为在configure生成pyconfig.h中,包含了

1
#define HAVE_DEV_PTMX 1

但在P4A的pyconfig.h中,这里是

1
#undef HAVE_DEV_PTMX

可能的原因似乎Cygwin支持/dev/ptmx,但Android不支持。所以configure根据Cygwin的情况就错误地定义了HAVE_DEV_PTMX。同样多情况还有HAVE_KILLPG,也得#undef掉。

最棘手的当属Modules/posixmodule.c说找不到fdatasync的编译错误。这个函数定义在$ANDROID_NDK/platforms/android-9/arch-arm/usr/include/unistd.h中,这个目录也已经添加到了Android.mk中,不应该找不到才对。通过使用ndk-build NDK_LOG=1 V=1来仔细查看每个步骤发现,NDK默认使用了android-3的API,即使你定义了LOCAL_C_INCLUDES也没用。所以它其实包含的是android-3下的unistd.h,而android-3是不支持fdatasync的,那个函数被放在#if 0中。于是我不得不添加了一个Application.mk,内容只有一行:

1
APP_PLATFORM := android-9

至此,Python 3.2已经可以用NDK编译,生成libpython3.2.so了。

还能用VC编译吗?

我仍然希望同一份源代码也能用VC编译生成Windows版的Python。这基本上只有一个问题,Android的pyconfig.h和Windows的pyconfig.h不同。于是我把前者命名为pyconfig.android.h,后者命名为pyconfig.win.h,并分别在编译脚本和Pre-Build Event里把对应的pyconfig.xxx.h覆盖拷贝成pyconfig.h。这样一来,不同的编译系统就都可以顺利编译了。

合在一起

在附件里面你可以找到所有我修改过的文件。在编译之前,你必须设置一个环境变量,名字为“ANDROID_NDK”,只想你的NDK根目录。

Python_for_android_patches.7z