交叉编译Python-2.7.13到ARM(aarch32)—— 支持sqlite3
2017-03-21 21:56
736 查看
作者:彭东林
邮箱:pengdonglin137@163.com
QQ: 405728433
开发板: qemu + vexpress-a9 (参考: http://www.cnblogs.com/pengdonglin137/p/6442583.html)
工具链: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320)
Python版本: Python-2.7.13
可以看到这里找不到_collections模块。
对比x86_64的编译结果:
而aarch32的编译结果:
可以看到,aarch32上面缺少了很多库, 比如_collections.so,将来这些库会被安装到/usr/lib/python2.7/lib-dynload下面, 所以下面要说的就是将缺少的这些库弄回来!
然后执行./mk2_make.sh可以看到:
在刚开始的时候,self.extensions中还是全的,但是经过下面的处理后, 很多库都被remove了:
第15行的注释可以看到,如果sys.builtin_module_names中含有extensions中的库,那么这个库就会从extensions中remove。从目前的分析看,交叉编译的时候,setup.py的import sys导入的应该是PC机上面的环境,导致sys.builtin_module_names的值也是PC上面python运行环境的值(可以在PC的终端下输入python,查看sys.builtin_module_names的值)。
然后重新配置、编译、安装, 最后重新制作ramdisk文件,启动板子,重新执行下面的测试:
可以看到,测试成功了。
下面开始一致sqlite3到板子上面,同时让python也增加多sqlite3的支持。
然后修改制作ramdisk的脚本:
这样在板子上面就可以使用sqlite3了,但是此时python还无法使用,需要重新编译python,并指定sqlite3的lib和include的路径,修改mk1_config.sh如下:
这样在Makefile调用setup.py时就会将sqlite3相关的模块编译进来,然后再次执行mk2_make.sh和mk3_install.sh,然后我们可以检查一下:
可以看到,库已经很全了。
编写测试sqlite3的脚本sq_demo.py如下:
下面是输出结果:
完。
邮箱:pengdonglin137@163.com
QQ: 405728433
环境
主机: ubuntu14.04 64bit开发板: qemu + vexpress-a9 (参考: http://www.cnblogs.com/pengdonglin137/p/6442583.html)
工具链: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320)
Python版本: Python-2.7.13
概述
前面一篇博文(交叉编译Python-2.7.13到ARM(aarch32)平台)介绍了移植python到aarch32上面,但是发现有很多模块都不能用,可以在板子上面执行下面的命令测试一下:[root@vexpress ]# python /usr/lib/python2.7/test/test___all__.py Traceback (most recent call last): File "/usr/lib/python2.7/test/test___all__.py", line 3, in <module> import unittest File "/usr/lib/python2.7/unittest/__init__.py", line 58, in <module> from .result import TestResult File "/usr/lib/python2.7/unittest/result.py", line 9, in <module> from . import util File "/usr/lib/python2.7/unittest/util.py", line 2, in <module> from collections import namedtuple, OrderedDict File "/usr/lib/python2.7/collections.py", line 20, in <module> from _collections import deque, defaultdict ImportError: No module named _collections
可以看到这里找不到_collections模块。
对比x86_64的编译结果:
ls x86_64/build/lib.linux-x86_64-2.7/ array.so* _codecs_hk.so* cPickle.so* _curses_panel.so* future_builtins.so* itertools.so* mmap.so* parser.so* _socket.so* _sysconfigdata.py time.so* audioop.so* _codecs_iso2022.so* crypt.so* _curses.so* grp.so* _json.so* _multibytecodec.so* pyexpat.so* spwd.so* _sysconfigdata.pyc unicodedata.so* binascii.so* _codecs_jp.so* cStringIO.so* datetime.so* _hashlib.so* linuxaudiodev.so* _multiprocessing.so* _random.so* _sqlite3.so* _sysconfigdata.pyo zlib.so* _bisect.so* _codecs_kr.so* _csv.so* _elementtree.so* _heapq.so* _locale.so* nis.so* readline.so* _ssl.so* syslog.so* cmath.so* _codecs_tw.so* _ctypes.so* fcntl.so* _hotshot.so* _lsprof.so* operator.so* resource.so* strop.so* termios.so* _codecs_cn.so* _collections.so* _ctypes_test.so* _functools.so* _io.so* math.so* ossaudiodev.so* select.so* _struct.so* _testcapi.so*
而aarch32的编译结果:
$ls aarch32/build/lib.linux2-arm-2.7/ audioop.so* _codecs_iso2022.so* _codecs_tw.so* _ctypes.so* _elementtree.so* _json.so* mmap.so* nis.so* resource.so* termios.so* _codecs_cn.so* _codecs_jp.so* crypt.so* _ctypes_test.so* future_builtins.so* linuxaudiodev.so* _multibytecodec.so* parser.so* _sysconfigdata.py _testcapi.so* _codecs_hk.so* _codecs_kr.so* _csv.so* datetime.so* _hotshot.so* _lsprof.so* _multiprocessing.so* pyexpat.so* _sysconfigdata.pyc
可以看到,aarch32上面缺少了很多库, 比如_collections.so,将来这些库会被安装到/usr/lib/python2.7/lib-dynload下面, 所以下面要说的就是将缺少的这些库弄回来!
正文
1、通过分析setup.py发现问题
在函数build_extensions中刚开始self.extensions中存放的是需要编译库, 通过在加打印:diff --git a/setup.py b/setup.py index 54054c2..bc16bb1 100644 --- a/setup.py +++ b/setup.py @@ -178,6 +178,7 @@ class PyBuildExt(build_ext): def build_extensions(self): + print "build_extensions enter." # Detect which modules should be compiled missing = self.detect_modules() @@ -191,6 +192,9 @@ class PyBuildExt(build_ext): extensions.append(ctypes) self.extensions = extensions + for ext in self.extensions: + print "extensions: ", ext.name + # Fix up the autodetected modules, prefixing all the source files # with Modules/ and adding Python's include directory to the path. (srcdir,) = sysconfig.get_config_vars('srcdir') @@ -217,6 +221,8 @@ class PyBuildExt(build_ext): # Python header files headers = [sysconfig.get_config_h_filename()] headers += glob(os.path.join(sysconfig.get_path('include'), "*.h")) + + print "builtin_module_names: ", sys.builtin_module_names for ext in self.extensions[:]: ext.sources = [ find_module_file(filename, moddirlist) for filename in ext.sources ] @@ -248,10 +254,15 @@ class PyBuildExt(build_ext): remove_modules.append(line[0]) input.close() + print "remove_modules: ", remove_modules + for ext in self.extensions[:]: if ext.name in remove_modules: self.extensions.remove(ext) + for ext in self.extensions[:]: + print "extensions: ", ext.name + # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's # a small set of useful ones. @@ -1618,13 +1629,13 @@ class PyBuildExt(build_ext): # Platform-specific libraries - if host_platform == 'linux2': + if host_platform == 'linux2' or host_platform == 'linux2-arm': # Linux-specific modules exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) ) else: missing.append('linuxaudiodev') - if (host_platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6', + if (host_platform in ('linux2','linux2-arm' 'freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8') or host_platform.startswith("gnukfreebsd")): exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) ) @@ -1755,6 +1766,10 @@ class PyBuildExt(build_ext): ## ext = Extension('xx', ['xxmodule.c']) ## self.extensions.append(ext) +# print "missing: ", missing +# for ext in self.extensions: +# print "extensions: ", ext.name + return missing def detect_tkinter_explicitly(self): @@ -2229,6 +2244,8 @@ Topic :: Software Development """ def main(): + print "sys.path: ", sys.path + print "cross_compiling: ", cross_compiling # turn off warnings when deprecated modules are imported import warnings warnings.filterwarnings("ignore",category=DeprecationWarning)
然后执行./mk2_make.sh可以看到:
sys.path: ['/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13', '/home/pengdonglin/src/qemu/python_cross_compile/aarch32/build/lib.linux2-arm-2.7', '/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13/Lib', '/home/pengdonglin/src/qemu/python_cross_compile/Python-2.7.13/Lib/plat-linux2', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload'] cross_compiling: True build_extensions enter. extensions: _struct extensions: _ctypes_test extensions: array extensions: cmath extensions: math extensions: strop extensions: time extensions: datetime extensions: itertools extensions: future_builtins extensions: _random extensions: _collections extensions: _bisect extensions: _heapq extensions: operator extensions: _io extensions: _functools extensions: _json extensions: _testcapi extensions: _hotshot extensions: _lsprof extensions: unicodedata extensions: _locale extensions: fcntl extensions: pwd extensions: grp extensions: spwd extensions: select extensions: parser extensions: cStringIO extensions: cPickle extensions: mmap extensions: syslog extensions: audioop extensions: crypt extensions: _csv extensions: _socket extensions: _sha extensions: _md5 extensions: _sha256 extensions: _sha512 extensions: termios extensions: resource extensions: nis extensions: binascii extensions: pyexpat extensions: _elementtree extensions: _multibytecodec extensions: _codecs_kr extensions: _codecs_jp extensions: _codecs_cn extensions: _codecs_tw extensions: _codecs_hk extensions: _codecs_iso2022 extensions: _multiprocessing extensions: linuxaudiodev extensions: _ctypes builtin_module_names: ('__builtin__', '__main__', '_ast', '_bisect', '_codecs', '_collections', '_functools', '_heapq', '_io', '_locale', '_md5', '_random', '_sha', '_sha256', '_sha512', '_socket', '_sre', '_struct', '_symtable', '_warnings', '_weakref', 'array', 'binascii', 'cPickle', 'cStringIO', 'cmath', 'errno', 'exceptions', 'fcntl', 'gc', 'grp', 'imp', 'itertools', 'marshal', 'math', 'operator', 'posix', 'pwd', 'select', 'signal', 'spwd', 'strop', 'sys', 'syslog', 'thread', 'time', 'unicodedata', 'xxsubtype', 'zipimport', 'zlib') remove_modules: ['DESTLIB=$(LIBDEST)', 'MACHDESTLIB=$(BINLIBDEST)', 'DESTPATH=', 'SITEPATH=', 'TESTPATH=', 'MACHDEPPATH=:$(PLATDIR)', 'EXTRAMACHDEPPATH=', 'TKPATH=:lib-tk', 'OLDPATH=:lib-old', 'COREPYTHONPATH=$(DESTPATH)$(SITEPATH)$(TESTPATH)$(MACHDEPPATH)$(EXTRAMACHDEPPATH)$(TKPATH)$(OLDPATH)', 'PYTHONPATH=$(COREPYTHONPATH)', 'posix', 'errno', 'pwd', '_sre', '_codecs', '_weakref', 'zipimport', '_symtable', 'GLHACK=-Dclear=__GLclear', 'xxsubtype'] extensions: _ctypes_test extensions: datetime extensions: future_builtins extensions: _json extensions: _testcapi extensions: _hotshot extensions: _lsprof extensions: parser extensions: mmap extensions: audioop extensions: crypt extensions: _csv extensions: termios extensions: resource extensions: nis extensions: pyexpat extensions: _elementtree extensions: _multibytecodec extensions: _codecs_kr extensions: _codecs_jp extensions: _codecs_cn extensions: _codecs_tw extensions: _codecs_hk extensions: _codecs_iso2022 extensions: _multiprocessing extensions: linuxaudiodev extensions: _ctypes Python build finished, but the necessary bits to build these modules were not found: _bsddb _curses _curses_panel _sqlite3 _ssl _tkinter bsddb185 bz2 dbm dl gdbm imageop ossaudiodev readline sunaudiodev zlib To find the necessary bits, look in setup.py in detect_modules() for the module's name.
在刚开始的时候,self.extensions中还是全的,但是经过下面的处理后, 很多库都被remove了:
for ext in self.extensions[:]: ext.sources = [ find_module_file(filename, moddirlist) for filename in ext.sources ] if ext.depends is not None: ext.depends = [find_module_file(filename, moddirlist) for filename in ext.depends] else: ext.depends = [] # re-compile extensions if a header file has been changed ext.depends.extend(headers) # platform specific include directories ext.include_dirs.extend(incdirlist) # If a module has already been built statically, # don't build it here if ext.name in sys.builtin_module_names: self.extensions.remove(ext)
第15行的注释可以看到,如果sys.builtin_module_names中含有extensions中的库,那么这个库就会从extensions中remove。从目前的分析看,交叉编译的时候,setup.py的import sys导入的应该是PC机上面的环境,导致sys.builtin_module_names的值也是PC上面python运行环境的值(可以在PC的终端下输入python,查看sys.builtin_module_names的值)。
2、 解决
这里为了简单起见,我们只需把刚才出问题的判断注释掉,如下:@@ -233,8 +239,8 @@ class PyBuildExt(build_ext): # If a module has already been built statically, # don't build it here - if ext.name in sys.builtin_module_names: - self.extensions.remove(ext) + #if ext.name in sys.builtin_module_names: + # self.extensions.remove(ext) # Parse Modules/Setup and Modules/Setup.local to figure out which # modules are turned on in the file.
然后重新配置、编译、安装, 最后重新制作ramdisk文件,启动板子,重新执行下面的测试:
[root@vexpress ]# python /usr/lib/python2.7/test/test___all__.py test_all (__main__.AllTest) ... BaseHTTPServer Bastion CGIHTTPServer ConfigParser Cookie DocXMLRPCServer HTMLParser MimeWriter Queue SimpleHTTPServer ... ... 'xml.sax.xmlreader', 'xmllib', 'xmlrpclib'] Following modules failed to be imported: ['ctypes.wintypes', 'dbhash', 'gzip', 'idlelib.AutoComplete'] ok ---------------------------------------------------------------------- Ran 1 test in 9.345s OK
可以看到,测试成功了。
下面开始一致sqlite3到板子上面,同时让python也增加多sqlite3的支持。
3、支持sqlite3
首先到http://www.sqlite.org/download.html 下载最新的sqlite3的源码,这里我用的是sqlite-autoconf-3170000.tar.gz,然后进行交叉编译,下面是交叉编译的脚本mk.sh:#!/bin/bash export PATH=/home/pengdonglin/src/qemu/aarch32/arm-2014.05/bin:$PATH ../sqlite-autoconf-3170000/configure --host=arm-none-linux-gnueabi \ --prefix=`pwd` make -j4 make install
然后修改制作ramdisk的脚本:
#!/bin/bash sudo rm -rf rootfs sudo rm -rf tmpfs sudo rm -rf ramdisk* sudo mkdir rootfs sudo cp ../busybox-1.24.2/_install/* rootfs/ -raf sudo mkdir -p rootfs/proc/ sudo mkdir -p rootfs/sys/ sudo mkdir -p rootfs/tmp/ sudo mkdir -p rootfs/root/ sudo mkdir -p rootfs/var/ sudo mkdir -p rootfs/mnt/ sudo cp etc rootfs/ -arf sudo cp -arf ../arm-2014.05/arm-none-linux-gnueabi/libc/lib rootfs/ #python sudo mkdir -p rootfs/usr pushd rootfs/usr sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/bin . sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/lib . sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/include . sudo cp -raf /home/pengdonglin/qemu/thiry_part/Python/aarch32/share . sudo /home/pengdonglin/qemu/aarch32/arm-2014.05/bin/arm-none-linux-gnueabi-strip lib/python* popd 31 #sqlite3 32 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/bin/* rootfs/bin/ 33 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/include/* rootfs/include/ 34 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/lib/* rootfs/lib/ 35 sudo cp -raf /home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/share/* rootfs/usr/share sudo mkdir -p rootfs/dev/ sudo mknod rootfs/dev/tty1 c 4 1 sudo mknod rootfs/dev/tty2 c 4 2 sudo mknod rootfs/dev/tty3 c 4 3 sudo mknod rootfs/dev/tty4 c 4 4 sudo mknod rootfs/dev/console c 5 1 sudo mknod rootfs/dev/null c 1 3 sudo rm -rf rootfs/lib/*.a sudo rm -rf rootfs/lib/*.la sudo ../arm-2014.05/bin/arm-none-linux-gnueabi-strip rootfs/lib/* sudo dd if=/dev/zero of=ramdisk bs=1M count=100 sudo mkfs.ext4 -F ramdisk sudo mkdir -p tmpfs sudo mount -t ext4 ramdisk ./tmpfs/ -o loop sudo cp -raf rootfs/* tmpfs/ sudo umount tmpfs sudo gzip --best -c ramdisk > ramdisk.gz sudo mkimage -n "ramdisk" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img
这样在板子上面就可以使用sqlite3了,但是此时python还无法使用,需要重新编译python,并指定sqlite3的lib和include的路径,修改mk1_config.sh如下:
#!/bin/bash export PATH=/home/pengdonglin/qemu/aarch32/arm-2014.05/bin:$PATH ../Python-2.7.13/configure --prefix=`pwd` \ --host=arm-none-linux-gnueabi \ --build=x86_64-linux-gnu \ --enable-ipv6 \ --enable-shared \ ac_cv_file__dev_ptmx="yes" \ ac_cv_file__dev_ptc="no" \ LDFLAGS="-L/home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/lib" \ CPPFLAGS="-I/home/pengdonglin/qemu/thiry_part/SQlite3/aarch32/include"
这样在Makefile调用setup.py时就会将sqlite3相关的模块编译进来,然后再次执行mk2_make.sh和mk3_install.sh,然后我们可以检查一下:
$ls aarch32/build/lib.linux2-arm-2.7/ array.so* _codecs_hk.so* cPickle.so* datetime.so* _heapq.so* _locale.so* _multiprocessing.so* _random.so* _socket.so* _sysconfigdata.pyc audioop.so* _codecs_iso2022.so* crypt.so* _elementtree.so* _hotshot.so* _lsprof.so* nis.so* resource.so* spwd.so* syslog.so* binascii.so* _codecs_jp.so* cStringIO.so* fcntl.so* _io.so* math.so* operator.so* select.so* _sqlite3.so* termios.so* _bisect.so* _codecs_kr.so* _csv.so* _functools.so* itertools.so* _md5.so* ossaudiodev.so* _sha256.so* strop.so* _testcapi.so* cmath.so* _codecs_tw.so* _ctypes.so* future_builtins.so* _json.so* mmap.so* parser.so* _sha512.so* _struct.so* time.so* _codecs_cn.so* _collections.so* _ctypes_test.so* grp.so* linuxaudiodev.so* _multibytecodec.so* pyexpat.so* _sha.so* _sysconfigdata.py unicodedata.so*
可以看到,库已经很全了。
4、测试
重新制作ramdisk文件,启动系统。编写测试sqlite3的脚本sq_demo.py如下:
#!/usr/bin/python import sqlite3 #open database conn = sqlite3.connect('test.db') print "Opened database successfully"; conn.execute('''CREATE TABLE COMPANY (ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL, AGE INT NOT NULL, ADDRESS CHAR(50), SALARY REAL);''') print "Table created successfully"; #insert conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \ VALUES (1, 'Paul', 32, 'California', 20000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \ VALUES (2, 'Allen', 25, 'Texas', 15000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \ VALUES (3, 'Teddy', 23, 'Norway', 20000.00 )"); conn.execute("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) \ VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 )"); conn.commit() print "Records created successfully"; #select cursor = conn.execute("SELECT id, name, address, salary from COMPANY") for row in cursor: print "ID = ", row[0] print "NAME = ", row[1] print "ADDRESS = ", row[2] print "SALARY = ", row[3], "\n" print "Operation done successfully"; #delect conn.execute("DELETE from COMPANY where ID=2;") conn.commit() print "Total number of rows deleted :", conn.total_changes cursor = conn.execute("SELECT id, name, address, salary from COMPANY") for row in cursor: print "ID = ", row[0] print "NAME = ", row[1] print "ADDRESS = ", row[2] print "SALARY = ", row[3], "\n" print "Operation done successfully"; conn.close()
下面是输出结果:
[root@vexpress ]# python /tmp/sq_demo.py Opened database successfully Table created successfully Records created successfully ID = 1 NAME = Paul ADDRESS = California SALARY = 20000.0 ID = 2 NAME = Allen ADDRESS = Texas SALARY = 15000.0 ID = 3 NAME = Teddy ADDRESS = Norway SALARY = 20000.0 ID = 4 NAME = Mark ADDRESS = Rich-Mond SALARY = 65000.0 Operation done successfully Total number of rows deleted : 5 ID = 1 NAME = Paul ADDRESS = California SALARY = 20000.0 ID = 3 NAME = Teddy ADDRESS = Norway SALARY = 20000.0 ID = 4 NAME = Mark ADDRESS = Rich-Mond SALARY = 65000.0 Operation done successfully
完。
相关文章推荐
- 交叉编译Python-2.7.13到ARM(aarch32)平台
- 交叉编译Python-2.7.13到ARM(aarch64)平台
- 交叉编译Python-3.6.0到aarch64/aarch32 —— 支持sqlite3
- 交叉编译Python-3.6.0到aarch64/aarch32 —— 支持sqlite3
- 交叉编译场景分析(arm-linux)(七)--编译sqlite
- ubuntu12.04 (32/64 bits) 安装配置 arm-linux-gcc-4.5.1 交叉编译工具链
- 交叉编译场景分析(arm-linux)(七)--编译sqlite
- 如何交叉编译Python到ARM-Linux平台
- 交叉编译Python3.6.2,使用海思arm-hisiv200-linux-gcc,移植到arm开发板上
- 如何交叉编译Python到ARM-Linux平台
- ios 32/64位 lame静态库libmp3lame.a 编译,支持arm64 armv7s x86_64 i386 armv7
- 交叉编译Python至嵌入式arm
- 交叉编译场景分析(arm-linux)(七)--编译sqlite
- arm-linux-gcc sqlite3 交叉编译
- 交叉编译场景分析(arm-linux)(七)--编译sqlite
- Qt5.3.0的移植安装与测试(交叉编译,用于arm,支持tslib触摸屏)
- aarch64(ARMv8)交叉编译环境下载
- ubuntu12.04 (32/64 bits) 安装配置 arm-linux-gcc-4.5.1 交叉编译工具链
- ubuntu12.04 (32/64 bits) 安装配置 arm-linux-gcc-4.5.1 交叉编译工具链
- 交叉编译场景分析(arm-linux)(七)--编译sqlite