python3.7移植记录

预览

编译主机:Ubuntu20.04 Linux version 5.8.0-53-generic
python版本及源码地址: https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
交叉编译工具:arm-oe-linux-gnueabi-gcc(gcc version 4.9.2)

编译记录

# 表示注释
$ 表示指令

1. 创建python项目

创建本次编译项目文件夹python

# 创建python项目文件, src用于存放源码,build_1表示第一次编译项目
$ mkdir -p python/src
$ mkdir -p python/build_1
$ tree python -d
python
├── build_1
└── src

2. 下载源码

$ cd python/src
$ wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
# 解压到build_1
$ tar -Jxvf Python-3.7.3.tar.xz -C ../build_1
$ ls ../build_1
Python-3.7.3

3. 安装主机版本

3.1 主机python

先检查主机上有没有python

$ python3 --version
Python 3.8.10

交叉编译时会检查主机上有没有对应版本的python(只要前两个版本号相同就可以, 推荐主机的版本号不低于目标版本号),安装主机python有两种方式,一是下载源码,本地编译安装(不推荐);二是使用apt在线安装(推荐)

  • apt安装

推荐使用这个方式安装

# 先添加第三方维护的PPA软件源,apt安装python时会从这个地址获取python
$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt-get update

# 安装需要的python, 保证前两个版本号相同就可以
$ sudo apt-get install python3.7

# 安装完成之后, 主机上可能就有多个版本python3,使用update-alternatives可以很方便的管理应用版本, 格式如下
# update-alternatives --install link name path priority
# link 表示软连接
# name 表示注册的应用的名称
# path 表示应用的正式路径
# priority 表示优先级,自定义设置, 数字越大优先级越大

# 这里3700 > 380, 表示优先使用python3.8
$ sudo update-alternatives --install  /usr/bin/python3 python3 /usr/bin/python3.7 3700
$ sudo update-alternatives --install  /usr/bin/python3 python3 /usr/bin/python3.8 380
# 设置成功后,update-alternatives会在/etc/alternatives/下创建应用的软连接, 通过这个链接管理不同版本
# 这里python3的调用路径为: /usr/bin/python3 --> /etc/alternatives/python3 --> /usr/bin/python3.7


# 这样就从原来的python3.8切换到了python3.7, 编译完成后最好再切换回去
$ python3 --version
Python 3.7.13
  • 源码安装

先下载源码, 解压, 进入源码

#--enable-optimizations 启动优化,编译会需要很长的时间, 不是必选的
$ ./configure --prefix=/usr/local/python3.7 --enable-optimizations
# 编译,安装后将会安装到/usr/local/python3.7
# 安装时可能会提示权限不足, 最好使用sudo
$ make
$ sudo make install

# 安装成功后,设置主机python环境, 同样使用update-alternatives管理多个版本
$ sudo update-alternatives --install  /usr/local/python3.7/bin/python3 python3 /usr/bin/python3.7 3700
$ sudo update-alternatives --install  /usr/bin/python3 python3 /usr/bin/python3.8 380

3.2 问题总结

编译完成后可能会遇到这种情况, 有些模块没有安装成功,有些模块未找到
在这里插入图片描述

3.2.1 _ctypes编译失败

安装_ctypes需要依赖libffi,编译主机版本直接安装libffi-dev即可。但是编译目标版本的python时就需要下载libffi源码,这一点见下一节。

$ sudo apt install libffi-dev

安装libffi-dev后
在这里插入图片描述

3.2.2 模块未找到

在这里插入图片描述
这是因为主机上缺少相关的依赖库,相关依赖库如下:
_bz2 _dbm _gdbm
_hashlib _lzma _sqlite3
_ssl _tkinter _uuid
readline

这里只找到一下这几个有效的库, 使用apt-get安装即可

模块依赖库
_bz2libbz2-dev
_gdbmlibgdbm-dev
_sqlite3libsqlite3-dev
_lzmaliblzma-dev

安装之后如下:
在这里插入图片描述
注意:如果编译arm版本的python时,如果也需要安装这里个库, 最好使用源码安装,经过交叉编译后才能安装到arm版本的python中。

4. 编译目标版本

4.1 基本流程

# 先清除编译主机版本时生成的中间文件
$ make clean

# 创建安装目录install
$ mkdir install

# 配置编译环境
# 1. 交叉编译环境 export PATH=$PATH:编译工具gcc的目录的路径
$ export PATH=$PATH:编译工具gcc的目录的路径
# 2. 安装路径使用绝对路径
# 3. 这里使用了变量LDFLAGS,CPPFLAGS, 后面如果要添加其他依赖环境, 都可以拷贝到python的安装路径下
$ ./configure --host=arm-oe-linux-gnueabi \
--build=x86_64-linux-gnu \
--target=arm-oe-linux-gnueabi --disable-ipv6 \
--prefix=$PWD/install \
ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=yes \
LDFLAGS="-L$PWD/install/lib" \
CPPFLAGS="-I$PWD/install/include"

# 编译,安装
$ make
$ make install

4.2 问题总结

4.2.1 lsb_release指令调用失败

在这里插入图片描述
参考这篇文章:https://blog.csdn.net/tao_627/article/details/90901563

# 将lsb_release.py和CommandNotFound复制到主机python中
$ sudo cp /usr/share/pyshared/lsb_release.py /usr/local/python3.7/lib/python3.7/
$ sudo cp -fr /usr/lib/python3/dist-packages/CommandNotFound   /usr/local/python3.7/lib/python3.7/

# 将__pycache__子目录中的文件名中带有38名字(有的是35)的文件更改为37
$ ls -l /usr/lib/python3/dist-packages/CommandNotFound/__pycache__
总用量 48
-rw-r--r-- 1 root root 13503 510 10:26 CommandNotFound.cpython-37.pyc
-rw-r--r-- 1 root root 13503 527 16:12 CommandNotFound.cpython-38.pyc-bak
-rw-r--r-- 1 root root   199 510 10:26 __init__.cpython-37.pyc
-rw-r--r-- 1 root root   199 527 16:13 __init__.cpython-38.pyc-bak
-rw-r--r-- 1 root root  1464 510 10:26 util.cpython-37.pyc
-rw-r--r-- 1 root root  1464 527 16:13 util.cpython-38.pyc-bak
4.2.2 _ctypes安装失败

和编译主机时一样,由于缺少依赖库所以导致_ctypes安装失败, 这里需要使用源码安装libffi。
libffi源码地址:ftp://sourceware.org/pub/libffi/libffi-3.3.tar.gz

  1. 先编译libffi
# 下载源码
$ wget ftp://sourceware.org/pub/libffi/libffi-3.3.tar.gz
$ tar -zxvf libffi-3.3.tar.gz
$ cd libffi-3.3
$ mkdir install
$ ./configure --host=arm-oe-linux-gnueabi --build=x86_64-linux-gnu --prefix=`pwd`/install
$ make

# 需要注意的是,在当前目录make install时总是提示: make: "install"已是最新
# 解决办法:make之后会在当前目录生成arm-oe-linux-gnueabi的文件夹, 先进入这个文件夹,再执行make install。 这个arm-oe-linux-gnueabi对应--host=指定的名称
$ cd arm-oe-linux-gnueabi
$ make install

# 编译安装之后, 拷贝一份到python的安装路径下,假设python安装路径/opt/python3.7.3/install/
$ cp -rfp install/* /opt/python3.7.3/install/

  1. 重新编译后,_ctype已经从编译失败的列表里面消失了
    在这里插入图片描述
4.2.3 _hashlib安装失败

解决_ctype编译失败后, 仍然还有一个_hashlib编译失败, 于_ctype一样, 先找到_hashlib所依赖的库。查看之前的编译日志, 可以看到_hashlib依赖了ssl, 同时日志也显示了ssl编译失败,所以需要先解决ssl的问题。
在这里插入图片描述
在这里插入图片描述
这里我选择重新安装openssl
openssl源码:https://www.openssl.org/source/old/1.1.0/openssl-1.1.0l.tar.gz

# 下载并解压到本地
$ wget https://www.openssl.org/source/old/1.1.0/openssl-1.1.0l.tar.gz
$ tar -zxvf openssl-python-0.1.1.tar.gz
$ cd openssl-1.1.1i
# --prefix= 指定安装路径
# --cross-compile-prefix= 指定编译链
# 注意, 这里使用了sudo,否则可能会出现“This system (linux-x86_64) is not supported”的错误
$ sudo ./config no-asm shared no-async --prefix=`pwd`/install --cross-compile-prefix=/opt/sdk/bin/arm-oe-linux-gnueabi/arm-oe-linux-gnueabi-

# ./config 生成的Makefile, 如果arm是32位系统, 先删除Makefile中的 -m64 编译选项
$ make
$ make install

openssl编译完成后,重新编译python,查看“./configure --help”,–with-openssl=可以指定openssl路径
在这里插入图片描述

# 使用--with-openssl=指定openssl
$ ./configure --host=arm-oe-linux-gnueabi \
--build=x86_64-linux-gnu \
--target=arm-oe-linux-gnueabi \
--disable-ipv6 \
--enable-optimizations \
--with-openssl=`pwd`/../Modules/openssl-1.1.1i/install \
--prefix=`pwd`/install \
ac_cv_file__dev_ptmx=yes \
ac_cv_file__dev_ptc=yes \
LDFLAGS="-L$PWD/install/lib" \
CPPFLAGS="-I$PWD/install/include"
# 重新编译,安装
$ make
$ make install

重新编译python之后,ssl已经编译成功
在这里插入图片描述

5. 模块安装

5.1 创建python模块交叉编译环境

修改/etc/sudoers,添加:Defaults env_keep += “PYTHONPATH”

在python源码目录下创建脚本mk_lib_config.sh,用于保存python模块交叉编译环境。

$ cat mk_lib_config.sh
export CROSS_COMPILE=arm-oe-linux-gnueabi-
export CC export CC="${CROSS_COMPILE}gcc"
export LDSHARED="${CC} -shared"
export LDFLAGS="-L${PWD}/install/lib"
export CFLAGS="-I${PWD}/install/include/python3.7m"
export PYTHONPATH=$PYTHONPATH:${PWD}/install/lib/python3.7/site-packages

${PWD}/install 表示python的安装路径, 安装模块时会自动安装到这个python的环境下, 这里使用了PWD,所以一定使用的时候一定要先cd到python源码目录下,再执行

$ source mk_lib_config.sh

5.2 asn1crypto模块

源码地址: https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz

# 下载到本地
$ wget https://files.pythonhosted.org/packages/fc/f1/8db7daa71f414ddabfa056c4ef792e1461ff655c2ae2928a2b675bfed6b4/asn1crypto-0.24.0.tar.gz
$ tar -zxvf asn1crypto-0.24.0.tar.gz
$ cd asn1crypto-0.24.0

$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

模块安装成功的关键:

  1. 配置交叉编译环境, 一般都是使用 export
  2. 配置python模块交叉编译环境,参考上一节
  3. 安装时指定安装路径, --prefix=pwd/…/…/Python-3.7.3/install

5.3 certifi模块

certifi源码:https://files.pythonhosted.org/packages/06/a9/cd1fd8ee13f73a4d4f491ee219deeeae20afefa914dfb4c130cfc9dc397a/certifi-2020.12.5.tar.gz

$ wget https://files.pythonhosted.org/packages/06/a9/cd1fd8ee13f73a4d4f491ee219deeeae20afefa914dfb4c130cfc9dc397a/certifi-2020.12.5.tar.gz
$ tar -zxvf certifi-2020.12.5.tar.gz
$ cd certifi-2020.12.5
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

5.4 chardet模块

chardet源码:https://files.pythonhosted.org/packages/ee/2d/9cdc2b527e127b4c9db64b86647d567985940ac3698eeabc7ffaccb4ea61/chardet-4.0.0.tar.gz

$ wget https://files.pythonhosted.org/packages/ee/2d/9cdc2b527e127b4c9db64b86647d567985940ac3698eeabc7ffaccb4ea61/chardet-4.0.0.tar.gz
$ tar -zxvf chardet-4.0.0.tar.gz
$ cd chardet-4.0.0
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

5.5 crcmod模块

crcmod源码:https://files.pythonhosted.org/packages/6b/b0/e595ce2a2527e169c3bcd6c33d2473c1918e0b7f6826a043ca1245dd4e5b/crcmod-1.7.tar.gz

$ wget https://files.pythonhosted.org/packages/6b/b0/e595ce2a2527e169c3bcd6c33d2473c1918e0b7f6826a043ca1245dd4e5b/crcmod-1.7.tar.gz
$ tar -zxvf crcmod-1.7.tar.gz
$ cd crcmod-1.7
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

5.6 keyring模块

$ wget https://files.pythonhosted.org/packages/b2/aa/71f2e7990a33a23dfcb3a96b87a9b3029664553f3dae4ec08a6f536183ea/keyring-17.1.1.tar.gz
$ tar -zxvf keyring-17.1.1.tar.gz
$ cd keyring-17.1.1
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

安装时并没有提示明显的错误,但是查看日志发现有一个依赖库SecretStorage没有安装,这里也手动安装一下。
在这里插入图片描述

$ wget https://files.pythonhosted.org/packages/cd/08/758aeb98db87547484728ea08b0292721f1b05ff9005f59b040d6203c009/SecretStorage-3.3.1.tar.gz
$ tar -zxvf SecretStorage-3.3.1.tar.gz
$ cd SecretStorage-3.3.1
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

SecretStorage依赖jeepney,同样也安装一下, 方法都一样。

在这里插入图片描述
jeepney安装完成后,再往后依次安装SecretStorage和keyring,最终还发现还依赖了cryptography,cryptography再上一节中还未解决,所以keyring先安装到这里
在这里插入图片描述

5.7 keyrings.alt 模块

$ wget https://files.pythonhosted.org/packages/62/a4/cfa759dc4a5113d653a1dfdbd61011e88fe7abb7a476c8ca10f37e2a789c/keyrings.alt-3.1.1.tar.gz
$ tar -zxvf keyrings.alt-3.1.1.tar.gz
$ cd keyrings.alt-3.1.1
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

keyrings.alt依赖了six, 安装six
在这里插入图片描述

$ wget https://files.pythonhosted.org/packages/94/3e/edcf6fef41d89187df7e38e868b2dd2182677922b600e880baad7749c865/six-1.13.0.tar.gz
$ tar -zxvf six-1.13.0.tar.gz
$ cd six-1.13.0
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

安装six之后,重新安装keyrings.alt

5.8 modbus-tk 模块

$ wget https://files.pythonhosted.org/packages/ce/e9/30d86eb912bf868b8c97698b5747f10cf72dc26c674fd030249bc3275484/modbus_tk-1.1.2.tar.gz
$ tar -zxvf modbus_tk-1.1.2.tar.gz
$ cd modbus_tk-1.1.2
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

同样, 安装pyserial, 再重新安装modbus_tk
在这里插入图片描述

$ wget https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz
$ tar -zxvf pyserial-3.5.tar.gz
$ cd pyserial-3.5
$ python3 setup.py install --prefix=`pwd`/../../Python-3.7.3/install

5.9 pycrypto 模块

使用pycryptodome替换pycrypto, 
  1. 如果之前安装了pycrypto, 先把pycrypto卸载掉, 否则会冲突。
  2. 安装pycryptodome, 下载地址https://files.pythonhosted.org/packages/88/7f/740b99ffb8173ba9d20eb890cc05187677df90219649645aca7e44eb8ff4/pycryptodome-3.10.1.tar.gz
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值