昨天在研究如何在嵌入式Linux上搭建Python运行环境,因为有了Python之后,很多工具例如GoAgent之类的东西就可以用上场了。昨天成功编译了Python2.6,参考了网上很多方法,但最后无果而终,现在总结了一套自己的编译方法,基本上可以秒杀所有Python版本的交叉编译,这里做一个总结。我的编译环境是Debian64位 无桌面版本,体积很小巧,安装在办公室电脑虚拟机里,在家里也可以远程编译代码。
首先在Python网站下载最新版源代码,这里我使用Python 3.3版本。解压下,有下面这堆东西。
接着,编辑Modules/Setup.dist,把需要用到的模块,去掉注释。
因为我打算把_socket,math,time,md5,sha1,select等模块静态编译进去(这样就不用lib-dynload里的一堆so文件都可以使用那些功能了)。
为了支持中文的decode和encode,下面两个模块也要编译进去。
如果你把zlib去掉了注释,要先交叉编译zlib,把编译出来的两个头文件和一个libz.a放到/usr/local/或者其他编译器能够发现的地方。
下面在configure之前,需要做一些小动作,不然会提示出错。
root@dev:~/Python-3.3.2# echo ac_cv_file__dev_ptmx=no > config.site
root@dev:~/Python-3.3.2# echo ac_cv_file__dev_ptc=no >> config.site
root@dev:~/Python-3.3.2# export CONFIG_SITE=config.site
root@dev:~/Python-3.3.2# ./configure CC=mipsel-linux-gcc CXX=mipsel-linux-g++ AR=mipsel-linux-ar RANLIB=mipsel-linux-ranlib –host=mipsel-linux –build=mipsel –disable-ipv6
我的交叉编译工具是mipsel-linux-*。如无意外,运行完毕应该得到Makefile文件。
编辑Makefile,在CONFIGURE_LDFLAGS后面添加 -s -static 两个选项。
下一步,开始编译。
root@dev:~/Python-3.3.2# make python
如无意外,当前目录下就可以得到python。因为我前面忘了加-s参数,所以编译出来体积有点大。可以使用strip工具去掉调试信息和一些不必要的内容,不影响运行。
strip之后,文件大小从8MB变为3MB。不过还是蛮大的,试试使用UPX压缩一下。工具下载:http://upx.sourceforge.net/
UPX之后,文件大小为 1 MB。对程序运行效率会有影响,不过只在启动的时候有影响,不会影响正常解释脚本的速度 😀
使用scp或者ftp复制该文件到路由器上,看看能否执行。
可以正确显示版本号,不过无法进入命令行,提示缺少encodings,那是因为还没有把Python的Lib复制过来。如果是Python2.x的版本,在这里已经可以运行使用了。所以,剩下只需要把要用到的标准库文件都复制过来就行了。
复制一份Lib目录,然后把不要的库像tkinter的全部删掉,encodings下除gbk和utf8以外的其它编码也不需要。
剩下5MB大小。复制到路由的对应目录下,比如说 /tmp/root/python/lib/python3.3,同时设置 export PYTHONHOME=/tmp/root/python。
再尝试运行,发现缺少 _sysconfiguredata.py 文件,这个文件在Modules里应该能找到,或者别的地方,把它复制过来,放到标准库目录下就OK。
因为标准库有5MB那么大,不是很方便写到Flash上,所以可以考虑把标准库压缩成一个Zip文件。
在python3.3目录下,使用批处理把所有py扩展名,通过 python3 -m py_compile *.c 编译成pyc文件,然后删除原来的py文件,接着执行
zip -9r python33.zip *
得到的文件大小为1MB。(我的python2.6的大小是500KB)。然后复制python33.zip到 /tmp/root/python/lib/python33.zip。就可以使用了。
其实,像 pyinstaller和py2exe这类压缩工具,也是用了同样的方法,而我这里是打包python运行环境到嵌入式Linux上。
比较一下 Python2.6 和 Python3.3 的在路由器上的体积。
Python2.6: 不带库 800KB,带基本标准库 1.3MB
Python3.3:不带库 1MB,带基本标准库 2.1MB
个人比较喜欢Python2.6的版本,因为不论是体积还是运行速度,都好很多。配合100KB的 bottlepy 网页开发框架,编写了一个简单的页面。
之前移植Python到开发板时,最头疼的是标准库太麻烦,打包成zip也没成功过,幸亏有空间放。
目前我编译的版本就只有两个文件,python和python26.zip,使用起来很方便,可以自己写个编译脚本,方便生成不同平台的这两个文件了。 🙂
你这个是针对703n编译的吗?
不一定的,只要搭建好了交叉编译环境即可。
头大。
赞!没有遇到 pgen 被编译成目标平台上的文件不能运行的问题么?
不知道pgen是在哪个步骤用到的,我是直接make python就得到python了。make Parser/pgen才会产生pgen,不过我好像不需要它 🙂
难道是因为我那个是直接 make 所以才遇到的?我当初是用 Funtoo 的 crossdev 在搞,遇到不少问题。(现在我那个 Funtoo 的 host 上的 Python 也没法升级了……)
对了,你这样编译出来的只有二进制文件没有库文件呢,lxml 之类的 C 扩展能用么?
c扩展这些应该可以单独编译吧,保证链接库正常使用就醒了。
不过我为了精简,都是静态编译的,没有用到一个so文件。
看来是因为我要的模块比较多的原因,好大哦,不过带 readline 啊 ssl 啊 zlib 啊之类的=w=
-rwxr-xr-x 1 root root 5.4K Sep 15 00:15 /usr/local/bin/python3.3
-r-xr-xr-x 1 root root 4.0M Sep 15 00:15 /usr/local/lib/libpython3.3m.so.1.0
-rw-r–r– 1 root root 2.2M Sep 15 00:43 /usr/local/lib/python33.zip
Parser/pgen 那个问题我通过 hack 的办法编译了一个 x86-64 的并且设置它的时间为将来以免被 make 重建。
PS: 我的目标是 Kindle Paperwhite,还有几十 M 的 / 以及整整一个 G 的 /mnt/us 🙂
好厉害,你编译的是动态链接库的版本吧。不过so文件好大,估计你没有strip?
strip 前 8M 呢。差不多那个 Setup.dist 里所有可用的模块我都编译了。
你可能把日韩等其他的文字编码以及ssl也编译进去了?
嗯,还有 unicodedata 也在哦=w=
出差归来,竟然发现小虾更新了
我的文章喵~~ http://lilydjwg.is-programmer.com/2013/9/16/cross-compile-zsh-and-python-3-3-for-kindle.40781.html
今天才刚刚发现小虾的博客,看了不少文章,真心觉得不错,以后会常来学习的,大神级的人物。膜拜一下!
bcm新出一款802.11ac的芯片,是ARM架构的,性能很高(当然对应路由器价格也不便宜400~900都有)
有点高端了,arm可以装android了吧
也许吧,不过配置可能跟不上(128M或256M的RAM)……还是跑跑路由常用的系统比较好
几位大神,如果将python交叉编译完后放到一个新的系统(系统为X86 i386-linux-gnu),运行python后,在导入模块base64、tempfile、random等时出问题,跑出浮点数异常(Floating point exception),请问这个是交叉编译的问题吗?
谢谢了
少便宜了什么模块吗???或者编译器没有启用浮点数支持?
谢谢了!
这个问题已经解决了,应该是我在交叉编译的时候一些参数没有配置好!
现在又有一个新的问题,请问你在用python安装lxml模块的时候(python setup.py install)有出现这种错误:
lxml/includes/etree_defs.h:13:32: error: libxslt/xsltconfig.h: No such file or directory
…..
src/lxml/lxml.etree.c:340:26: error: libxslt/xslt.h: No such file or directory
src/lxml/lxml.etree.c:341:32: error: libxslt/xsltconfig.h: No such file or directory
src/lxml/lxml.etree.c:342:35: error: libxslt/xsltInternals.h: No such file or directory
src/lxml/lxml.etree.c:343:32: error: libxslt/extensions.h: No such file or directory
src/lxml/lxml.etree.c:344:31: error: libxslt/documents.h: No such file or directory
src/lxml/lxml.etree.c:345:31: error: libxslt/transform.h: No such file or directory
src/lxml/lxml.etree.c:346:31: error: libxslt/xsltutils.h: No such file or directory
src/lxml/lxml.etree.c:347:30: error: libxslt/security.h: No such file or directory
src/lxml/lxml.etree.c:348:31: error: libxslt/variables.h: No such file or directory
底下一大堆这种错误。
我已经通过yum安装了libxml2-devel libxslt-devel python-devel libxml2 libxslt2 这些都不是和Python安装在同一个目录下面,因为我就想将python移植到另外一个系统中。
那就不要用lxml咯,不然你只能交叉编译lxml和libxslt。
求大神开发个openwrt下运行的代理脚本吧,我自己搭建python运行您写的那个代理始终运行不起来…..
不知为何我make python的时候,提示我没有sys/xattr.h这个文件,我看看我的工具链里面真的没有!我的平台是pogoplug,求解
博主也玩开源路由路由么?很不错,有一种路由应用方案不知你有没兴趣,蛮有意思的,可以结合微信一起玩
求Python3.3压缩成1.5M的IPK文件~打算不装U盘在703n上实现看看。
这个版本应该做不到这么小。
不知道什么python的版本可以放到703n下呢?
请问win系统中如何编译?
应该更麻烦,建议还是Linux比较好。
请问在配置的时候出现了,要如何处理?
checking for python interpreter for cross build… configure: error: python3.3 interpreter not found
你的问题是怎么解决的 我遇到和你一样的问题了
这边安装您的方法,目前可以运行pathon,但是基本库压缩后,再运行pathon,会有下面的问题:
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named ‘encodings’
Aborted
这个如何处理?
你好,我想在HG8342R上部署Python。目前计划安装Python2.7,以便使用Goagent等应用。详细问题我发布在quora上了,可以麻烦您看一下吗?先谢过了。
https://www.quora.com/Is-it-possible-to-install-Python-on-a-router
我参照你的步骤做的,然后也遇到了缺少 _sysconfiguredata.py 文件的问题,但是我没有在Module里面或者其他地方找到它,google这个文件也无果,只有你这边提到了这个文件,所以如果你有的话麻烦给我发一个吧,项目急,万分感谢!!!邮箱:[email protected]
Pingback引用通告: Python 2.7.3静态编译 | Sept's Blog
最近准备搞一个samba4 ADS的包, 曾经想把python静态编译,但samba4 waf编译非常的麻烦,很多依赖检测,最后作罢
很赞啊,不知道交叉编译后的python,运行在嵌入式linux上,是不是能支持桌面python的所有库呢?比如numpy、django之类的?
能解决依赖关系的话是可以的,除非某些库要求特定的环境。 django肯定是没问题,不过django比较庞大,在嵌入式上可能跑得不快。
你好,看了你的教程也想编译py到路由器里,flash只有8m,可是交叉编译各种问题,能不能把你编译好的发给我一份,谢谢![email protected]
最近在做把python交叉编译到xilinx开发板上,按照这篇博客的流程,编译出了python但是import re模块会报错,提示找不到_sre,我检查了最后link时候的命令,发现_sre.o是在那个命令里面的。。。
因此使用不了bottle框架。
不知道您是否能指点一下。
试试直接import _sre
[root@hk ~]# python
imPython 2.7.5 (default, Jun 24 2015, 00:41:19)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import _sre
>>>
你好,压缩标准库那段没怎么看懂。编译成功可以运行。
然后我把py全部编译成pyc然后删除py,就无法启动Python了
说找不到codecs模块。
我以为python是先找pyc文件的?
有个很奇怪的现象。我把python静态编译以后,放在开发板上运行,显示sh: not found.
用readelf看了下,发现program interpreter是/usr/ld.so.1。这个东西在哪?。。。
和 micropython 比呢?应该会更小?