基于arm-linux-gnueabihf 移植python3.6和第三方库

摘要

项目需要,要在嵌入式板子上移植python,预期需要的第三方库为numpy、pandas和pymodbus及其依赖库。记录踩坑过程。
主机为32位ubuntu
目标板为32位arm板子,
交叉编译工具链为arm-linux-gnueabihf-
readelf -h 文件名 查看文件的使用架构

  1. 嵌入式的第三方库无法使用pip install 安装
  2. 如果需要使用pip instal的话还需要_ctype和zlib
  3. numpy需要_ctypes
  4. pymodbus需要_ssl和zlib
  5. pandas需要_bz2
  6. 需要使用主机版pyhon的解释器,才能对目标板python的setup进行解释

准备

python3.7源码:、numpy源码:、pandas源码:、pymodbus源码:、six源码:、serial源码:、opsenssl源码:、bzip2源码:
基于arm-linux-gnueabihf 移植python3.6和第三方库_第1张图片

大致流程

编译主机依赖库,编译主机python,编译目标板python,打包至目标板,编译目标板第三方库
注:所有操作在root账户下进行
sudo -i 进入root

编译依赖库

openssl for _ssl

主机openssl编译

openssl参考
参考上文,设置编译位置为/opt/hostssl

cd 源码路径
export 	CC=
./configure --prefix=/opt/hostssl
make
make install
mv /usr/bin/openssl /usr/bin/openssl.old    		//将旧版本的openssl进行备份
ln -s /usr/local/bin/openssl /usr/bin/openssl    	//将新版本的openssl进行软链接
openssl version
OpenSSL 1.1.1q  5 Jul 2022

如果提示找不到动态库,做如下操作

export LD_LIBRARY_PATH=/opt/hostssl/lib:$LD_LIBRARY_PATH  #添加库路径
echo $LD_LIBRARY_PATH  #查看库路径

目标板openssl编译

openssl参考
参考上文,编译位置选择:–prefix=/opt/ssl

cd 源码路径
make clean
mkdir /opt/ssl
./config no-asm -shared --prefix=/opt/ssl \
	CC=arm-linux-gnueabihf-gcc \
	CXX=arm-linux-gnueabihf-g++ \
	AR=arm-linux-gnueabihf-ar \
	RANLIB=arm-linux-gnueabihf-ranlib

修改makefile文件
搜索 m32 选项并删除,共两处(如是64位系统则是m64)
如不删除则编译时会出现以下错误

error: unrecognized command line option '-m32'

修改完成后

make
make install

libbz2 for _bz2

libbz2的编译

py3.7 for arm 仓库
该仓库中的libbz2.so.1.0.6和libbz2.1.0和_bz2.cpython-37m-arm-linux-gnueabihf.so可以直接使用之后再说这一步

zlib

主机板zlib编译

unzip zlib-master.zip
cd zlib-master
export CC=gcc
./configure
make 
make install

目标板zlib编译

mkdir _install
export CC=arm-linux-gnueabihf-gcc	//设置交叉编译器
./configure --enable-shared --prefix=/opt/zlib
make
make install
#复制到交叉编译工具
cp -rfp /opt/zlib/* /usr/local/arm-linux/gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf

libffi for _ctypes

可以不看!!本人尝试失败了
py3.7 for arm 仓库
_ctypes.cpython-37m-arm-linux-gnueabihf.so可以直接使用之后再说这一步

主机板_ctypes编译

apt-get install libffi-dev

目标板_ctypes编译

tar -xzvf libffi-3.4.2.tar.gz
cd libffi-3.4.2
mkdir /opt/libffi
export CC=arm-linux-gnueabihf-gcc
./configure CC=arm-linux-gnueabihf-gcc -host=arm-linux-gnueabihf --build=i686-linux-gnu target=arm-linux-gnueabihf --enable-shared --prefix=/opt/libffi
make 
make install
#复制到交叉编译期
cp -rfp /opt/libffi/* /usr/local/arm-linux/gcc-linaro-7.5.0-2019.12-i686_arm-linux-gnueabihf

编译主机python

cd python源码包位置
tar -xf Python-3.7.11.tar.xz #解压
cd Python-3.7.11/
vi Modules/Setup.dist

如图取消ssl的注释(这一步如果能成功最好,不成功就把注释加回来)
基于arm-linux-gnueabihf 移植python3.6和第三方库_第2张图片
可能是因为系统本身就带有ssl的库,这一步即使不取消注释,编译出的目标板python也有_ssl库
同理,取消掉关于zlib的注释;

export CC=  # 返回默认编译器
./configure
make
make install

测试是否可用

rm /usr/bin/python3 #删除原有的软连接
ln -s /usr/local/bin/python3.7 /usr/bin/python3 #新建软连接
root@baoyu-ubuntu:# python3 -V
Python 3.7.11
root@baoyu-ubuntu:/home/baoyu/libs/Python-3.7.11# python3
Python 3.7.11 (default, Sep  6 2022, 13:21:16) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> import _ssl
>>> 

测试结果python版本为3.7.11,ssl和_ssl可以正常导入

编译目标板python

cd 源码解压位置
make distclean
./configure
make Parser/pgen # 先编译解析器
mkdir armpy # 创建空目录来交叉编译
mkdir /opt/python3
cp -rfp /opt/zlib/* /opt/python3/ # 复制zlib到python文件夹
cp -rfp /opt/libffi/* /opt/python3/ # 复制libffi到python文件夹
cp ./Parser/pgen ./armpy/Parser/  #拷贝解释器
touch -t 12312359 ./armpy/Parser/pgen #解释器日期修改成当年最后一分钟,防止被替换
root@baoyu-ubuntu:/home/baoyu/libs/Python-3.7.11# ll ./armpy/Parser/pgen
-rwxr-xr-x 1 root root 294896 1231  2022 ./armpy/Parser/pgen*
###准备编译
#解决ctypes找不到头文件和库文件
export CFLAGS="-I/opt/python3/include -I/opt/python3/include/python3.7m -L/opt/python3/lib" 
./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 \
             --disable-ipv6 \
             --prefix=/opt/python3 \
             --with-ensurepip=yes \
             --enable-optimizations \
             ac_cv_file__dev_ptmx=yes \
             ac_cv_file__dev_ptc=yes 

修改Setup和Setup.dist,同上,取消注释指定ssl库的位置,
此外再取消关于zlib部分的注释
编译

make
make install

这时候make到最后可能会提示 failed to build _ctypes,看结果是因为没找到ffi的头文件
在这里插入图片描述
基于arm-linux-gnueabihf 移植python3.6和第三方库_第3张图片
解决办法:把这句话加在configure前(亲测无效,仅提供失败案例)

#解决ctypes找不到头文件和库文件
export CFLAGS="-I/opt/python3/include -I/opt/python3/include/python3.7m -L/opt/python3/lib" 

再次make的时候就会在这里找头文件
在这里插入图片描述
但是!!!还是失败了

移植至目标板

压缩编译好的python

cd /opt
tar zcvf python3.7.tar.gz python3

目标板解压

tar xzvf python3.7.tar.gz

测试

cd python3.7/bin
root@zynq:/media/sdcard/sdtest/python3.7/bin# ./python3.7 -V
Python 3.7.11
root@zynq:/media/sdcard/sdtest/python3.7/bin# ./python3.7
Python 3.7.11 (default, Sep  6 2022, 13:57:22) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import _bz2      
Traceback (most recent call last):
  File "", line 1, in <module>
ModuleNotFoundError: No module named '_bz2'
>>> import _ssl

可见_ssl模块可以导入,bz2模块无法使用

目标板python添加_bz2

把libbz2.so.1.0.6和libbz2.so.1.0拷贝到目标板/usr/lib下
把_bz2.cpython-37m-arm-linux-gnueabihf.so拷贝至/media/sdcard/sdtest/python3.7/lib/python3.7/lib-dynload
测试

root@zynq:/media/sdcard/sdtest/python3.7/bin# ./python3.7
Python 3.7.11 (default, Sep  6 2022, 13:57:22) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import bz2
>>> import _bz2
>>> 

成功
同理添加_ctypes

编译目标板第三方库

以numpy为例
添加库路径

cd ~
vi .bashrc
# 末尾输入
export PYTHONPATH=$PYTHONPATH:/opt/python3/lib/python3.7/site-packages
# 保存并退出 .bashrc
source .bashrc

编译numpy源码

cd 源码解压位置
export CROSS_COMPILE=arm-linux-gnueabihf- \
export CC="${CROSS_COMPILE}gcc" \
export CXX=arm-linux-gnueabihf-g++ \
export LDFLAGS="-L/opt/python3/lib" \
export LDSHARED="${CC} -shared" \
export CFLAGS="-I/opt/python3/include/python3.7m"
python3 setup.py install --prefix=/opt/python3
#编译numpy时把C++那一句去掉

此时安装会提示缺少module【cython】,使用以下安装cython
pip临时换源换源参考文档

pip install *** -i https://pypi.tuna.tsinghua.edu.cn/simple
 python3 -m pip install cython -i https://pypi.tuna.tsinghua.edu.cn/simple

cyhton安装完成后,再次运行setup.py

python3 setup.py install --prefix=/opt/python3

可以看到一个numpy-1.8.2-py3.7-linux-i686.egg文件,同时还有easy-install.pth文件,将这两个文件拷贝至目标板python的site-packages即可使用。

附录

如果需要pip和setuptool的话,直接将主机/usr/local/lib/python3/site-packages下的pip和setuptool拷贝过去即可
基于arm-linux-gnueabihf 移植python3.6和第三方库_第4张图片
测试:

root@zynq:/media/sdcard/sdtest# python
Python 3.7.11 (default, Sep  6 2022, 19:53:25) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import zlib
>>> import _bz2
>>> import _ctypes
>>> import numpy
>>> import _ssl
>>> import pymodbus
>>> 

root@zynq:/media/sdcard/sdtest# python -m pip list
Package    Version
---------- -------
numpy      1.18.2
pip        20.1.1
pymodbus   2.5.3
pyserial   3.4
setuptools 47.1.0
six        1.16.0

你可能感兴趣的:(arm,linux,python,numpy)