二、python及第三方库编译
1.目的
在x86-64平台上生成arm平台上可执行的代码,在x86-64平台上编译python和python依赖库与第三方库,使之能运行在arm平台上。
2. 交叉编译背景
- 交叉编译链:CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ AR=arm-linux-gnueabihf-ar RANLIB=arm-linux-gnueabihf-ranlib
- 目标板子:arm(暂未定)
- python版本:3.12.4
- numpy==1.26.3
3.第三方库
分类:
- 数据分析和科学计算:pandas、numpy、matplotlib
- 机器学习:tensorflow、pytorch
- 图像处理:opencv
- 数据库接口:pymysql
一般使用:
- 查找库:在Python Package Index上查看找库
- 安装库:pip install <pkg>
- 导入库:import
4.整体思路
- 在x86主机上交叉编译zlib库
- 在x86主机上交叉编译openssl库
- 在x86主机上安装x86主机版本的python,称之为x86_python
- 在x86主机上交叉编译arm机版本的python,称之为arm_python
- 在x86主机上通过crossenv搭建arm_arm的运行虚拟环境
- 在crossenv虚拟环境中通过pip打包交叉编译第三方库——.whl形式
-----------------------------------------------------交叉编译工具已在一、里准备好----------------------------------
5.编译x86_zlib
- 下载zlib源码,我下载的是zlib1.3.1版本
- 解压缩包,我是依赖库的源码包放在~/Downloads/python_libs/rely/目录下(我看其他博主会解压两份源码用作x86_zlib编译和arm_zlib编译,我就用一个,大家根据各自需求来。)
- cd zlib-1.3.1
- 设置编译环境: ./configure,默认安装如下

- 执行编译安装 make&&make install ,此时安装成功(注:make install时可能会报错权限不够,此时执行sudo make install避免错误。
6.编译arm_zlib
1.此时在~/Downloads/python_libs/rely/zlib-1.3.1目录下
2.设置交叉编译器:
#(其实只设置第一个就够了)
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++
export AR=arm-linux-gnueabihf-ar
export RANLIB=arm-linux-gnueabihf-ranlib,
3.设置编译环境:./configure --prefix=~/Downloads/arm_python_libs/rely/arm_zlib --enable-shared
4.执行编译安装:make&&make install
7.编译x86_openssl
- 下载openssl-3.1.2版本源码
- 解压缩包,还是把源码包放在~/Downloads/python_libs/rely/目录下
- cd openssl-3.1.2
- 设置编译环境 :./config --prefix=/home/zoe/Downloads/python_lib/openssl
- 执行编译安装:make&&make install
- 此时检查一下主机自带的opensll版本 openssl version,我的是其它版本,所以还得先去掉主机自带的版本。要不然后面make的是时候报错找不到"xxxx"模块

- 备份主机旧版本:sudo mv /usr/bin/openssl /usr/bin/openssl.old
- 建立新的软连接:sudo ln -s /home/zoe/Downloads/python_lib/openssl/bin/openssl /usr/bin/openssl
- 编辑链接文件:sudo nano /etc/ld.so.conf.d/libc.conf
- 在libc.conf文件中添加:/home/zoe/Downloads/python_lib/openssl/lib64
- 重新加载配置:ldconfig
- 测试:openssl version,已经成功

8.编译arm_openssl
- 此时在~/Downloads/python_libs/rely/openssl-3.1.2目录下
- 设置编译环境 ./config no-asm --shared --cross-compile-prefix=arm-linux-gnueabihf- --prefix=~/Downloads/arm_python_libs/rely/arm_openssl
no-asm:表示不使用汇编代码加速编译
--cross-compile-prefix:指定交叉编译的前缀,执行此指令后会在Makefile中指定好交叉编译的工具,如下图是执行后的Makefile
3.在编译后生成的Makefile中有两处是 -m64 的标记要删除,因为交叉编译后是在32位的板子上运行,参考在linux下为arm开发板交叉编译openssl报错arm-linux-gcc.br_real: error: unrecognized command line option '-m64'_arm-linux-gnueabihf-gcc: error: unrecognized comma-CSDN博客
4.执行编译安装:make&&make install
9.编译x86_ctypes
使用这条指令:sudo apt-get install libffi-dev
10.编译arm_ctypes
- 下载源码包 libffi-3.4.2
- 解压放在~/Downloads/python_libs/rely/目录下
- cd libffi-3.4.2
- 设置编译环境:./configure CC=arm-linux-gnueabihf-gcc --host=arm-unknown-linux-gnueabihf --build=x86_64-linux-gnu --target=arm-linux-gnueabihf --enable-shared --prefix=~/Downloads/arm_python_libs/rely/arm_ctypes
- 执行编译安装:make&&make install
11.编译x86_python
1.安装依赖包
sudo apt-get install zlib1g-dev libbz2-dev libssl-dev libncurses5-dev libsqlite3-dev libreadline-dev tk-dev libgdbm-dev libdb-dev libpcap-dev xz-utils libexpat1-dev liblzma-dev libffi-dev libc6-dev
2.下载python源码3.12.4版本包
3.解压放到~/Downloads/python-3.12.4
4.mkdir x86_python #当前与Python-3.12.4在同一目录
5.cd python-3.12.4
6.修改Modules/Setup文件:sudo nano Modules/Setup
- 修改zlib部分(去掉zlib前面的注释#)
zlib zlibmodule.c -I /usr/local/include -L /usr/local/lib -lz
- 修改openssl部分
SSL=/home/zoe/Downloads/python_lib/openssl
_ssl _ssl.c \
DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-L$(SSL)/lib -lssl -lcrypto
5.编译并下载pyhton:先export CC= ,这里将编译器设置回来,默认去找gcc,再执行以下信息
./configure --prefix=/home/zoe/Downloads/x86_python
make #或者bear -- make ,可以生成编译信息.json文件,但是需要安装bear
make install
想要在这个过程中不安装pip时,使用 --without-ensurepip
3.进入x86_python目录,测试一个py示例,此时在x86本机上也可以import zlib来使用了
注:这里测试时需要进去x86_python/bin目录下,输入命令./python3.12,我是先进行了处理,把python3.12放到全局变量里。可以看以下操作。
zoe@zoe:~/Desktop$ python3.12
Python 3.12.4 (main, Jul 15 2024, 21:29:18) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import zlib
>>> import _ssl
>>> import ctypes
>>> print(1000)
1000
>>>
注:这里采用自动安装pip的方法,本版本python的pip版本不低就没有采取自动安装,如果自动版本太低,参考这篇:python及第三方库交叉编译 - Se7eN_HOU - 博客园 (cnblogs.com)
12.编译arm_python
- 目前的目录为~/Downloads/python-3.12.4
- 创建一个新文件夹:mkdir ~/Downloads/arm_rely_libs
- 将之前交叉编译好的arm_zlib、arm_openssl、arm_libffi的头文件和链接库复制到~/Downloads/arm_rely_libs
#将各个依赖库的内容都放入新建的文件夹中,按bin、include、lib、share等分类存
cp -rfp ~/Downloads/arm_python_libs/rely/arm_zlib/* ~/Downloads/arm_rely_libs/
cp -rfp ~/Downloads/arm_python_libs/rely/arm_openssl/* ~/Downloads/arm_rely_libs/
cp -rfp ~/Downloads/arm_python_libs/rely/arm_ctypes/* ~/Downloads/arm_rely_libs/
4.设置CFLAGS:
CFLAGS="-I/home/zoe/Downloads/arm_rely_libs/include -L/home/zoeDownloads/arm_rely_libs/lib"
5.设置LDFLAGS:
LDFLAGS="-L /home/zoe/Downloads/arm_rely_libs/lib"
6.编辑Modules/Setup文件启动依赖库
- 修改zlib
zlib zlibmodule.c -I/home/zoe/Downloads/arm_rely_libs/include - L/home/zoe/Downloads/arm_rely_libs/lib -lz
- 修改openssl
SSL=/home/zoe/Downloads/arm_rely_libs
_ssl _ssl.c \
-DUSE_SSL -I$(SSL)/inlude -I$(SSL)/include/openssl
-L$(SSL)/lib -lssl -lcrypto
7.执行命令进行编译环境设置
#创建安装目录
mkdir arm_py_build
./configure CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ AR=arm-linux-gnueabihf-ar RANLIB=arm-linux-gnueabihf-ranlib --host=arm-linux-gnueabihf --build=i686-linux-gnu --target=arm-linux-gnueabihf --enable-shared --disable-ipv6 --with-system-ffi ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=no --enable-optimizations --prefix=/home/zoe/Downloads/arm_py_build
#理解以上编译信息
1)CC:C编译器
2)CXX:C++编译器
3)AR:归档器
4)RANLIB;随机库索引生成器,加快链接过程
5)--host=arm-unknown-linux-gnueabihf :目标机类型是arm-linux-gnueabihf,通常用于32位ARM架构
6)--target=arm-linux-gnueabihf :指定了目标系统基于ARM架构
7)--enable-shared:
8) --disable-ipv6 :禁用对IPv6的支持。
9)ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=no:arm板子/dev目录下有ptmx,没有ptc
10) --enable-optimizations :启用编译优化,可能会启用一些提高性能的编译选项。
11) --prefix:指定安装路径
12)--with-build-python:指定用于构建过程中的Python解释器路径
13)disable-test-modules:禁用构建测试模块,这可以减少构建过程的时间和资源消耗。
14)--with-ensurepip=install:构建过程会包括 ensurepip 模块,并且会在安装Python解释器时,同时安装 pip 工具。
8.编译命令:
make HOSTPYTHON=/home/zoe/Downloads/x86_python/bin/python3 HOSTPGEN=/home/zoe/Downloads/Python-3.12.4/Parser/pgen
这里需要指定一个x86平台的python解释器,和python字节码生成器的路径,在python-3.12.4源码中。
9.执行:
make install HOSTPYTHON=/home/zoe/Downloads/x86_python/bin/python3
10.问题处理
- 交叉编译时需要在本机上有同版本的python,即前面已经编译生成的x86_python,因为交叉编译时需要同版本x86平台的解释器,但我的主机上自带了一个3.9version的python。
直接将x86_python/bin/python3.12放到全局环境中
参考链接:
ubuntu系统: ubuntu22.04安装python,并设置系统环境变量_ubuntu22.04 python-CSDN博客
注:不要像我一样傻傻的sudo apt-get remove python删除了自带的python,这样会导致下次开启虚拟机进入tty模式,没有桌面了。
13.通过crossenv交叉编译第三方库,例如:numpy
原理:
在x86主机上使用x86_python搭建arm_python的虚拟环境,然后在虚拟环境中打包arm_python的带三方库(交叉编译+wheel打包),这里以numpy为例。
步骤:
- 进入x86_python目录下:cd /home/zoe/Downloads/x86_python/bin
- 安装crossenv:./pip3 install crossenv
- 使用crossenv代表arm_python的虚拟环境:
./python3 -m crossenv /home/zoe/Downloads/arm_python/bin/python3 myvenv
1)./python3:当下目录的python
2)-m crossenv:
-m参数让 Python 作为模块运行,这里crossenv是一个用于创建交叉编译环境的模块。3)/home/zoe/Downloads/arm_python/bin/python3:目标平台上的python解释器路径
4)myvenv:创建的交叉编译的虚拟环境名称
5)如果你的想在虚拟环境中安装新版本pip,加上选项:--without-pip
note:这步我报错:unable to symlink....,我选择忽视了......
4.进入虚拟环境目录:cd myvenv/cross/bin
5.激活环境:source activate
6.(可选) 安装pip指定版本
#下载pip包
curl https://bootstrap.pypa.io/pip/3.x/get-pip.py -o get-pip.py -k
#安装pip
./python3 get-pip.py
7.在myvenv这个虚拟环境中的安装Cython:./pip3 install Cython
8.创建文件夹来放编译后的第三方库:mkdir /home/zoe/Downloads/arm_3rdparty
9.在 /home/zoe/Downloads/arm_3rdparty目录下创建requirements.txt(我把文件放在第三方目录里,便于管理)
10.sudo nano requirements.txt里面写上numpy和版本
numpy==1.26.3
11.交叉编译第三方库称为.whl格式的安装包:wheel是pip3的子命令(碰见问题,后续有解决方法)
#使用pip3工具根据requiremwnts.txt文件列出的依赖项创建轮子包
./pip3 wheel --wheel dir /home/zoe/Downloads/arm_3rdparty -r /home/zoe/Downloads/arm_3rdparty/requirement.txt
问题:
描述
最后第11步时,报错
Installing build dependencies ... done
Getting requirements to build wheel ... done
Installing backend dependencies ... error
error: subprocess-exited-with-error
× pip subprocess to install backend dependencies did not run successfully.
│ exit code: 1
╰─> [73 lines of output]
Collecting patchelf>=0.11.0
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.HTTPSConnection object at 0x7ec814d20080>: Failed to establish a new connection: [Errno 101] Network is unreachable')': /packages/83/ec/ac383eb82792e092d8037649b382cf78a7b79c2ce4e5b861f61519b9b14e/patchelf-0.17.2.1.tar.gz
解决
1.更新pip(报出提示信息包含升级版本,但这不是根本原因)
#查看pip版本
pip --version
#升级pip
sudo python3 -m pip install --upgrade pip
2.网络问题-->使用国内镜像源
#交叉编译指令时加上 -i http....
#常见地址
国内镜像地址: 阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/(我用的这个,https更安全)
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
3.报错不安全,应使用https
#交叉编译指令时加上 -i https....
./pip3 wheel --wheel dir /home/zoe/Downloads/arm_3rdparty -r /home/zoe/Downloads/arm_3rdparty/requirement.txt -i https://pypi.mirrors.ustc.edu.cn/simple/
14.移植到arm板子
原理:
移植arm_python文件夹、numpy-1.26.3-cp312-cp312-linux_arm.whl到目标板子上
步骤:
1.压缩文件夹:tar cvf arm_python.tar arm_python
2.转移压缩包和.whl文件
3.解压并放在/home/zoe/Downloads目录下
4.cd /home/zoe/Downloads/arm_python/bin
5.运行python:./python3
6.验证第三方库
1.验证pip
$ pip list
2.给.whl文件改名:假设arm板子型号是armv7l,则 mv /home/numpy-1.26.3-cp312-cp312-linux_arm.whl /home/numpy-1.26.3-cp312-cp312-linux_armv7l.whl
3.通过pip安装numpy,验证
./python3
>>import numpy
>>numpy.__version__
1.26.3
>>
其他参考博客
更多推荐
所有评论(0)