##master-page:HelpTemplate ##master-date:2004-05-15 22:02:16 #pragma section-numbers off #format wiki #language en <> = HOWTO Cross Compile Python for ARM -- by Leo Jay = == 前言 == 我需要在Arm9的s3c2410 CPU上运行python,以下是我的编译过程。 ===== host编译环境: ===== ubuntu 7.04, gcc 4.2.1, arm-linux-gcc 3.3.2 ===== 要cross compile的程序: ===== * sqlite 3.5.6, * python 2.5.1 == 编译sqlite == 先去 http://www.sqlite.org/download.html 下载最新的sqlite源代码,我这里用的是3.5.6版本的。 我推荐使用amalgamation版本的源代码,这个代码只有几个文件而已,编译起来方便,而且据说 编译器好的话,还可能编译出更高效的代码。 我下载的是 {{{ http://www.sqlite.org/sqlite-amalgamation-3.5.6.tar.gz }}} 先运行以下几步: {{{ tar zxf sqlite-amalgamation-3.5.6.tar.gz cd sqlite-3.5.6 ./configure --host=arm-linux --prefix=/usr/local/arm/3.3.2 --enable-shared --disable-readline --disable-dynamic-extensions }}} 以上是把sqlite解压缩,然后做一些配置,这里,我希望sqlite到时候安装到/usr/local/arm/3.3.2里,要生成动态链接库,不要readline,不要sqlite的动态扩展。 然后编辑Makefile,把CFLAG和CXXFLAG中的-g去掉,我们不用debug sqlite。 接下来就可以编译和安装sqlite了: {{{ make make install }}} 这一步就完成了sqlite的编译和安装了。 == 编译python == 先去http://www.python.org/download/下载最新版本的python源代码,我这里下载的是: {{{ http://www.python.org/ftp/python/2.5.1/Python-2.5.1.tar.bz2 }}} 先把python解压缩: {{{ tar jxf Python-2.5.1.tar.bz2 cd Python-2.5.1 }}} === 编译pc版本的语法解析器 === 由于在编译python的时候,需要先编译一个叫pgen的程序出来,用于生成语法解析器,所以我们要先生成一个pc版本的pgen: {{{ mkdir build.pc cd build.pc ../configure make Parser/pgen }}} 然后ls Parser一下,应该就能看到有pgen了。 === 修改configure === configure在检测编译器的printf是否支持%zd的时候,如果发现是在cross compile,就直接不干活了。这还了得? 把这一部分的检测代码去掉。这段代码起始于 {{{ echo "$as_me:$LINENO: checking for %zd printf() format support" >&5 echo $ECHO_N "checking for %zd printf() format support... $ECHO_C" >&6 if test "$cross_compiling" = yes; then }}} 结束于 {{{ cat >>confdefs.h <<\_ACEOF #define PY_FORMAT_SIZE_T "z" _ACEOF else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi }}} 把这两段以及中间的内容都删除掉就可以了。 === 编译arm版本的python === 有了语法解析器,就可以开始编译arm版本的python了。 {{{ mkdir ../build.arm cd ../build.arm ../configure --prefix=/home/leojay/test/arm-system-working/rootfs --disable-ipv6 --host=arm-linux --enable-shared }}} 先创建一个用于编译的目录build.arm,再对python做一些配置,如安装目录,不要ipv6,使用arm-linux的编译器,生成动态链接库。 ===== 修改Makefile ===== 之后就要对Makefile做一些修改,把 {{{ OPT= -DNDEBUG -g -O3 -Wall -Wstrict-prototypes }}} 一行中,去掉-g,我们不要debug python,-O3改为-O2,空间紧张O2就可以了。 在 {{{ PGEN= Parser/pgen$(EXE) }}} 一行的下面加上 {{{ PGEN_HOST= ../build.pc/Parser/pgen$(EXE) }}} 表明我们在HOST上运行的pgen 在要使用PGEN的地方改为PGEN_HOST: {{{ $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) }}} 改为: {{{ $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) -$(PGEN_HOST) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) }}} 修改所有''使用''新生成的python的地方。 所有如 ./$(BUILDPYTHON) 的地方,都改为python 如: {{{ platform: $(BUILDPYTHON) $(RUNSHARED) ./$(BUILDPYTHON) -E -c 'import sys ; from distutils.util import get_platform ; print get_platform()+"-"+sys.version[0:3]' >platform }}} 改为 {{{ platform: $(BUILDPYTHON) $(RUNSHARED) python -E -c 'import sys ; from distutils.util import get_platform ; print get_platform()+"-"+sys.version[0:3]' >platform }}} 这种地方比较多,大家小心修改。 ===== 修改setup.py ===== setup.py负责编译python的各个扩展模块。但是,由于python完全没有考虑cross compile,所以要做一些修改。 * PyBuildExt类: i. build_extension函数: 这个函数在编译了所有的extension后,会去load这些刚编译好的extension, 但我们在i686的电脑上显然不能load,所以要跳过这些操作。 在 build_ext.build_extension(self, ext)后面直接写一个return,不做load。 i. detect_modules函数: 函数的前两行是把/usr/local加到搜索目录中,我们的cross compiler一般不会直接安装在 /usr/local里面的,所以这两行去掉: {{{ add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') }}} lib_dirs, inc_dirs的设定中,把中括号里的那些都去掉。 以下所有模块都不要: {{{ cmath, ctypes, _testcapi, pwd, grp, spwd, mmap, audioop, imageop, rgbimg, readline, ssl, openssl, bdb, dbm, termios, nsl, ncurses, bz2, linuxaudiodev, ossaudiodev, tkinter }}} 由于python本身的问题,现在ctypes还不能在除i386以外的机器上运行,所以ctypes也去掉 编译sqlite的地方: {{{ for d in inc_dirs + sqlite_inc_paths: }}} 改为: {{{ for d in ['/usr/local/arm/3.3.2/include']: }}} 因为我的sqlite3安装在这里,如果这里不改的话,setup.py会在我的电脑上找sqlite * main函数: setup函数调用的时候,把要安装的scripts那一部分去掉 之后就可以make && make install了。 附上我修改后的 [[attachment:Makefile]] 和 [[attachment:setup.py]] 供大家参考 == 裁减python == python完全安装后,实在是很大,所以,要把一些肯定用不上的库去掉。 所以,再附上我的裁减脚本 [[attachment:cleanpy.sh]] 注意,由于我的python程序都运行在python -OO的参数下,所有的.py和.pyc都不需要, 只要有.pyo就可以了。所以,这个脚本会把所有的.py和.pyc都删除掉。 大家可以根据自己的需要做调整。 ---- 关于如何生成所有库的.pyo文件,可以参考我的这篇文章: http://wiki.woodpecker.org.cn/moin/LeoJay/PyPackage