python及第三方库交叉编译
一、前言:
网上关于python的交叉编译的文章很多,但是关于python第三库的交叉编译的文章就比较少了,而且很多标题是第三方库的交叉编译,但是实际上用到的都是不需要交叉编译就能用的库,可参考性不强,最近关于python及其第三方库的交叉编译也踩了不少坑,记录一下!
二、交叉编译介绍:
1、什么是交叉编译:在一个平台上生成另一个平台上的可执行代码。
2、为什么要交叉编译:在进行嵌入式系统的开发时,运行程序的目标平台通常具有有限的存储空间和运算能力,比如常见的ARM 平台,其一般的静态存储空间比较小,而CPU运算能力弱。这种情况下,在ARM平台上进行本机编译就不太可能了,为了解决这个问题,交叉编译工具就应运而生了。通过交叉编译工具,我们就可以在CPU能力很强、存储控件足够的主机平台上(比如PC上)编译出针对其他平台的可执行程序。
三、python及其第三方库的交叉编译背景
1、交叉编译链:rv1126-arm-buildroot-linux-gnueabihf-toolchain.tar.bz2
2、目标板子(target主机):armv7l
3、执行交叉编辑的主机(build主机):ubuntu18-x86_64
4、python版本:3.5.2
5、numpy==1.18.5
四、交叉编译的准备工作
build主机是我新安装的一个ubuntu18的新虚拟机,所以连gcc 都没有的
1、安装gcc: sudo apt-get install gcc-8 -y
2、将gcc-8指定成默认的gcc: sudo ln -s /usr/bin/gcc-8 /usr/bin/gcc
3、安装cmake: sudo apt-get install make cmake -y
4、安装libffi-dev 交叉编译 python 需要的依赖: sudo apt-get install libffi-dev
5、安装zip 解压压缩包使用:sudo apt-get install zip -y
五、交叉编译python及其第三方的思路
1、在build主机上交叉编译zlib库,这个是python源码安装必须的依赖库
2、在build主机上交叉编译openssl库,这个虽然不是源码安装必须的依赖库,但是大部分其他库都有可能使用到这个库
3、在build主机上安装build主机上的python版本,我们成为python-build
4、在build主机上交叉编译target主机上的python版本,我们称之为python-target
5、在build主机上通过crossenv搭建target-python的运行虚拟环境
6、在crossenv虚拟环境中通过pip打包交叉编译第三方库为.whl形式的
六、准备交叉编译工具
1、解压交叉编译链:说明不同的平台的使用的交叉编译链不同,但是思路和步骤是一样的。
tar jxvf rv1126-arm-buildroot-linux-gnueabihf-toolchain.tar.bz2
解压之后得到一个名为 host 的文件夹。
2、进入 host 目录: cd host
3、执行 relocate-sdk.sh 指令: ./relocate-sdk.sh (不是所有交叉编译链都需要这一步的)
4、将交叉编译链添加到环境变量:vim /etc/profile
5、在最后添加:export PATH=$PATH:/home/host/bin 这里的路径根据自己实际的路径进行修改即可。
6、重新加载环境变量:source /etc/profile
7、测试:arm-buildroot-linux-gnueabihf-gcc -v
七、准备openssl-build
这里我已经准备好了openssl-1.0.2g.tar.gz的压缩包,这里我尝试了openssl-1.1.1的版本,但是和python3.5.2不太合适,总是有问题,所以这里我使用的是openssl-1.0.2的版本
1、 解压源码包,这些源码包我都是放在/home路径下的:tar -xzvf openssl-1.0.2g.tar.gz
2、对压缩包进行重命名,区分是在build主机上用的还是在target主机上用的,在build主机上用的我都统一在后面加上_build,在target主机上使用的统一在后面加上_target
mv openssl-1.0.2g openssl-1.0.2g-build
3、cd openssl-1.0.2g-build
4、设置编译环境:./config --prefix=/home/openssl-1.0.2g-build/openssl-build
其中: --prefix是指定编译后的安装的路径
5、执行编译安装:make && make install 此时在/home/openssl-1.0.2g-build里面就会有openssl-build文件夹
6、因为安装的ubuntu18中默认的openssl是1.1.1,我们需要换成我们的openssl-1.0.2g
把以前的备份:sudo mv /usr/bin/openssl /usr/bin/openssl.old
7、建立新的软连接:sudo ln -s /home/openssl-1.0.2g-build/openssl-build/bin/openssl /usr/bin/openssl
8、编辑链接文件:vim /etc/ld.so.conf.d/libc.conf
9、在libc.conf文件中添加:/usr/openssl-1.0.2g-build/openssl-build/lib
10、重新加载配置:ldconfig
11、测试:openssl version ,已经变成1.0.2g版本了
八、准备openssl-target
1、同样是再次解压openssl源码包,这次解压的源码包用来交叉编译给target-python使用的:tar -xzvf openssl-1.0.2g.tar.gz
2、更改名字:mv openssl-1.0.2g openssl-1.0.2g-target
3、cd openssl-1.0.2g-target
4、设置编译环境:./config no-asm --shared --cross-compile-prefix=arm-buildroot-linux-gnueabihf- --prefix=/home/openssl-1.0.2g-target/openssl-target
解释: no-asm :加上 no-asm 表示不使用汇编代码加速编译,不然会报错
--cross-compile: 指定交叉编译链的前缀,这样在交叉编译openssl就会使用我们的交叉编译链进行交叉编译了
--prefix: 已经是交叉编译后的路径
5、在编译后生成的Makefile中有两处是 -m64 的标记要删除,因为交叉编译后是在32位的板子上运行,所以这一步也要改:sed -i 's/-m64//' Makefile
6、执行编译安装:make && make install
目前我们就把openssl-build和openssl-target都准备好了
九、准备zlib-build
1、解压源码包:unzip zlib1211.zip
2、改名:mv zlib-1.2.11 zlib-1.2.11-build
3、cd zlib-1.2.11-build
4、设置编译环境:./configure --prefix=/home/zlib-1.2.11-build/zlib-build
5、执行编译安装:make && make install
十、准备zlib-target
1、解压源码包:unzip zlib1211.zip
2、改名:mv zlib-1.2.11 zlib-1.2.11-target
3、cd zlib-1.2.11-target
4、设置交叉编译器:export CC=arm-buildroot-linux-gnueabihf-gcc 通过export 设置的环境变量都是临时一次性的,当shell窗口关闭了就失效了
5、设置编译环境:./configure --prefix=/home/zlib-1.2.11-target/zlib-target --enable-shared
6、执行编译安装:make && make install
目前我们也已经包zlib-build和zlib-target准备好了
十一、准备ctypes-build
这一步已经在准备工作中做了:sudo apt-get install libffi-dev
十二、准备ctypes-target
1、解压源码包:tar -xzvf libffi-3.2.1.tar.gz
2、改名:mv libffi-3.2.1 libffi-3.2.1-target
3、cd libffi-3.2.1-target
4、设置交叉编译器:export CC=arm-buildroot-linux-gnueabihf-gcc 如果这一步在准备zlib-target没有关闭shell窗口的时候,可以不用设置,因为已经设置过了,但是如果关了窗口就要重新设置了
5、设置编译环境:./configure CC=arm-buildroot-linux-gnueabihf-gcc --host=arm-buildroot-linux-gnueabihf --build=x86_64-linux-gnu target=arm-buildroot-linux-gnueabihf --enable-shared --prefix=/home/libffi-3.2.1-target/libffi-target
6、执行编译安装:make && make install
目前ctypes-build和ctypes-target也准备好了
十三、编译python-build
1、解压源码:tar xvf Python-3.5.2.tgz
2、改名:mv Python-3.5.2 python-3.5.2-build
3、cd /home/python-3.5.2-build
4、修改 Modules/Setup.dist文件:vim Modules/Setup.dist
a、修改关于openssl部分
b、修改关于zlib部分
5、将之前设置的交叉编译器改为默认的编译器:export CC= 这里=后面什么都不赋值就表示设置为空,这样就会去找默认的gcc了
6、设置编译环境,./configure --prefix=/home/python-build --without-ensurepip
--without-ensurepip:不安装pip,因为默认安装的pip版本太低了,所以一会我们自己安装pip
7、执行安装编译:make && make install
8、cd /home/python-build/bin
9、下载pip文件:curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py -k
10、安装pip: ./python3 get-pip.py
11、将该python-build添加到环境变量,设置为build主机上默认的python: export PATH=/home/python-build/bin:$PATH
12、安装Cython: pip3 install Cython
13、测试:python3
十四:编译python-targer
1、解压源码包:tar xvf Python-3.5.2.tgz
2、改名:mv Python-3.5.2 python-3.5.2-target
3、cd python-3.5.2-target
4、创建文件夹:mkdir /home/python-target
5、将之前准备的openssl-targer、zlib-targer、cytpes-targer的头文件和链接库复制到/home/python-targer
cp -rfp /home/zlib-1.2.11-target/zlib-target/* /home/python-target/
cp -rfp /home/libffi-3.2.1-target/libffi-target/* /home/python-target/
cp -rfp /home/openssl-1.0.2g-target/openssl-target/* /home/python-target/
6、设置CFLAGS: CFLAGS="-I/home/python-target/include -I/home/python-target/include/python3.5m -L/home/python-target/lib"
7、设置LDFLAGS: LDFLAGS="-L/home/python-target/lib"
8、vim Modules/Setup.dist
9、设置编译环境:注意这里我为了方便看,手动的给每个参数换行了,实际使用中不应该换行的
./configure CC=arm-buildroot-linux-gnueabihf-gcc
CXX=arm-buildroot-linux-gnueabihf-g++
AR=arm-buildroot-linux-gnueabihf-ar
RANLIB=arm-buildroot-linux-gnueabihf-ranlib
--host=arm-buildroot-linux-gnueabihf
--build=x86_64-linux-gnu
--target=arm-buildroot-linux-gnueabihf
--disable-ipv6
ac_cv_file__dev_ptmx=yes
ac_cv_file__dev_ptc=yes
--prefix=/home/python-target
--without-ensurepip
10、编译:make HOSTPYTHON=/home/python-build/bin/python3 HOSTPGEN=/home/python-3.5.2-build/Parser/pgen
11、执行:make install HOSTPYTHON=/home/python-build/bin/python3
目前位置我们就在build主机上已经编译好了python-build和python-target
十五、通过crossenv交叉编译第三方库例如:numpy
1、在build主机上使用python-build搭建python-target的虚拟环境,然后再虚拟环境中打包python-target的第三方库,这里以numpy为例:因为numpy是需要经过交叉编译才能使用的。
2、cd /home/python-build/bin
3、安装crossenv: ./pip3 install crossenv
4、使用crossenv代表python-target的虚拟环境:./python3 -m crossenv --without-pip /home/python-target/bin/python3 cross_venv
5、cd cross_venv/cross/bin
6、激活虚拟环境:source activate
7、curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py -k
8、./python3 get-pip.py
9、在cross_venv这个虚拟环境中的安装Cython:./pip3 install Cython
10、创建文件夹用来存放编译后的第三方:mkdir /home/target_lib
11、创建requestments.txt:vim requirements.txt 里面写上numpy
12、交叉编译第三方库成为.whl格式的安装包:./pip3 wheel --wheel-dir /home/target_lib -r requirements.txt
13、验证:cd /home/target_lib
14、注意,这里我们使用crossenv交叉编译后的numpy第三方库的后缀是linux_arm,而我们的目标板子是armv7l的,所以这里我们要手动的将
numpy-1.18.5-cp35-cp35m-linux_arm.whl改为numpy-1.18.5-cp35-cp35m-linux_armv7l.whl。不然会报错。这个坑,一直坑了我一个月的时间,尝试了很多方法,不知道是编译链的问题,还是编译过程的问题。将交叉编译后的numpy的.whl文件移植到目标板子的中,总是报错,突然灵光一闪,就手动改个名字,居然可以了,这坑简直是巨坑,坑了一个月的时间。
十六、移植到目标板子
将编译好的python-target打包 和 numpy-1.18.5-cp35-cp35m-linux_arm.whl(先不改名,移植到目标板子上在改名)移植到目标板子上
1、压缩python-target: tar cvf python-target.tar python-target
2、通过ftp工具,将python-target.tar和numpy-1.18.5-cp35-cp35m-linux_arm.whl ,移植到目标板子的/home下
3、解压python-target: tar xvf python-target.tar
4、cd /home/python-target/bin
5、验证在目标板子上运行python3
6、验证交叉编译的第三方
1、先下载pip: curl https://bootstrap.pypa.io/pip/3.5/get-pip.py -o get-pip.py -k
2、安装pip: ./python3 get-pip.py
3、配置pip源
a、mkdir ~/.pip
b、vi ~/.pip/pip.conf
c、添加如下代码
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn
4、验证pip
5、通过pip安装未改名的numpy第三方库:这是会报错:numpy-1.18.5-cp35-cp35m-linux_arm.whl is not a supported wheel on this platform.
6、改名: mv /home/numpy-1.18.5-cp35-cp35m-linux_arm.whl /home/numpy-1.18.5-cp35-cp35m-linux_armv7l.whl
7、重新安装验证:
到此python3及python需要的第三方库,类似numpy这样需要交叉编译的第三方库就完成了!其中其他库不一定都是完全一样的,但是大致流程是一样的可以参考借鉴。
python及第三方库交叉编译的更多相关文章
- python常用框架及第三方库
python常用框架及第三方库 一.Web框架 1.Django: 开源web开发框架,它鼓励快速开发,并遵循MVC设计,比较庞大,开发周期短.Django的文档最完善.市场占有率最高.招聘职位最多. ...
- .Net 常用插件及第三方库
.Net 常用插件及第三方库 一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址: ...
- python常用三方库 - openpyxl
目录 python常用三方库 - openpyxl 读取Excel文件 写入Excel文件 python常用三方库 - openpyxl openpyxl是一个第三方库, 可以处理xlsx格式的Exc ...
- Python学习--23 内建模块及第三方库
本文将介绍python里常用的模块.如未特殊说明,所有示例均以python3.4为例: $ python -V Python 3.4.3 网络请求 urllib urllib提供了一系列用于操作URL ...
- python 常用的标准库及第三方库
标准库Python拥有一个强大的标准库.Python语言的核心只包含数字.字符串.列表.字典.文件等常见类型和函数,而由Python标准库提供了系统管理.网络通信.文本处理.数据库接口.图形系统.XM ...
- Python常用的标准库及第三方库
标准库Python拥有一个强大的标准库.Python语言的核心只包含数字.字符串.列表.字典.文件等常见类型和函数,而由Python标准库提供了系统管理.网络通信.文本处理.数据库接口.图形系统.XM ...
- python自带库及第三方库api察看
今天发现一个很有意思的功能,python自带了所有库的文档查看器,配置如下: 配置pydoc服务,cmd中输入如下代码: python –m pydoc –p 1234 回车后 ,使用过程中,该窗口不 ...
- Python MySQL事务、引擎、索引及第三方库sqlalchemy
本节内容 1.数据库介绍2.事务3.引擎4.索引5.ORM sqlalchemy 1.数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数据库都有一 ...
- Python常用三方库安装
//首先更新pip python -m pip install --upgrade pip //一个类似Matlab的Plot绘制数据图的库. python -m pip install matplo ...
随机推荐
- day03_3_流程控制练习题
# 流程控制练习题 # 一.编程题 1.实现一个课程名称和课程代号的转换器:输入下表中的课程代号,输出课程的名称.用户可以循环进行输入,如果输入0就退出系统.(**使用****switch +whil ...
- VirtualBox 相关命令行
简介 由于之前项目有一个需求,则是自动化创建虚拟机并加载相关配置,创建虚拟机无法避免对于虚拟机系统的设置,因此采用导入虚拟机的方式,并通过查阅virtualbox相关手册,知晓virtualbox可以 ...
- git diff与linux diff的输出格式之unified format
前言 前面有一篇文章<一个有些意思的项目--文件夹对比工具(一)>,里面简单讲了下diff算法之--Myers算法. 既然是算法,就会有实现,比如git diff中有Myers的实现,gi ...
- Bellman-Ford算法与SPFA算法详解
PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...
- Spring源码 21 Bean生命周期
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- mysql中文乱码--存入mysql里的中文变成问号的解决办法
今天,服务器里测试的时候,发现存入数据库的中文全部变成问号了! 首先想到这是编码问题:于是乎再次设置数据库的编码为utf8 可是,问题仍然存在: 后来发现,这个问题的根源应该是: 虽然数据库编码是ut ...
- ESP32与MicroPython入门-01 搭建开发环境
ESP32简介 ESP32 是上海乐鑫公司开发的一款比较新的32位微控制器,它集成了WiFi及蓝牙等功能,有着性能稳定.功耗低.价格低廉等特点,非常适用于物联网开发,但也可以作为普通的MCU使用. E ...
- Redis的两种持久化机制
Redis的两种持久化机制 1.持久化机制 client--->redis(内存)--->内存数据-数据持久化--->磁盘 两种方法 快照(Snapshot) AOF(Append ...
- Mybatis框架--优化过程
0. 原代码预览 简单实现在数据库中插入数据 public void testInsert() throws IOException { //获取核心配置文件的输入流 InputStream is = ...
- ELK技术-Logstash
1.背景 1.1 简介 Logstash 是一个功能强大的工具,可与各种部署集成. 它提供了大量插件,可帮助业务做解析,丰富,转换和缓冲来自各种来源的数据. Logstash 是一个数据流引擎 它是用 ...