# build-python-deb **Repository Path**: duanyao/build-python-deb ## Basic Information - **Project Name**: build-python-deb - **Description**: 提供编译 pyhton(cpython)的 deb 包所需的配置文件。 - **Primary Language**: Shell - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-16 - **Last Updated**: 2024-11-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # build-python-deb ## 介绍 提供编译 python(cpython)的 deb 包所需的配置文件。 ## 选择构建环境 可以在 debian 系操作系统中使用本项目来构建 pyhton 的 deb 包。 不同的 python 版本有不同的构建环境最低版本要求,大致总结如下: | python 版本 | debian版本 | 支持编译 | 不支持的原因 | | -- | -- | -- | -- | | 3.11 | 10,11 | y | | | 3.13 | 10,11 | n/y | 需要 autoconf>=2.71,但系统只有 autoconf=2.69;通过手动安装 debian12 的 autoconf-2.71 后可以编译 | | 3.13 | 12 | y | | 建议构建环境的操作系统的版本选择等于部署环境的,否则构建出来的 python 可能无法在部署环境中安装或运行。这主要是因为不同的 debian 系版本一般只包含 libffi{6|7|8} 、libssl{1.1|3} 、libreadline{5|7|8} 之一,一个 python 二进制版本只能依赖其中之一。具体可以参考“构建和部署环境的兼容性”部分。 推荐使用 docker 容器作为构建环境,其它容器/虚拟机或者 chroot 环境也可以。 ## 构建和部署环境的兼容性 系统版本和python运行时依赖库的版本: | 系统版本 | libc6 | libffi | libssl | libreadline | libsqlite3-0 | | -- | -- | -- | -- | -- | -- | | deb10 | 2.28 | 6=3.2.1 | 1.1=1.1.1n | 5=5.2, 7=7.0 | 3.27.2 | | deb11 | 2.31 | 7=3.3 | 1.1=1.1.1w | 8=8.1 | 3.34.1 | | deb12 | 2.36 | 8=3.4.4 | 3=3.0.14 | 8=8.2 | 3.40.1 | | deb13 | 2.40 | 8=3.4.6 | 3t64=3.3.2 | 8t64=8.2 | 3.46.1 | | ub2004 | 2.31 | 7=3.3 | 1.1=1.1.1f | 5=5.2, 8=8.0 | 3.31.1 | | ub2204 | 2.35 | 7=3.3, 8=3.4.2 | 3=3.0.2 | 8=8.1.2 | 3.37.2 | | ub2404 | 2.39 | 8=3.4.6 | 3t64=3.0.13 | 8t64=8.2 | 3.45.1 | 注释: * deb == debian, ub == ubuntu, 2004 == 20.04 。 * libffi 的 `6=3.2.1` 表示 `libffi6-3.2.1`。libssl, libreadline 类似。 在不同构建环境中构建的 python deb 包可部署的环境: | python 版本 | 构建环境 | deb 包依赖 | 部署环境 | 部署环境(通过兼容仓库)| | -- | -- | -- | -- | -- | | 3.13 | deb10 | libc6 (>= 2.28), libffi6 (>= 3.0.10~rc8), libreadline7 (>= 7.0~beta), libsqlite3-0 (>= 3.25.0), libssl1.1 (>= 1.1.1) | deb10 | deb10~12, ub2004~2404 | | 3.13 | deb12 | libc6 (>= 2.35), libffi8 (>= 3.4), libreadline8 (>= 7.0~beta), libsqlite3-0 (>= 3.36.0), libssl3 (>= 3.0.0) | deb12,ub2204,ub2404 | 同左 | 注释: * “部署环境(通过兼容仓库)“是指通过给高版本的操作系统添加低版本系统的 apt 仓库,从而兼容针对低版本系统的软件包的方式。 * 没有差别的 deb 包依赖被省略了。 ## 安装构建依赖: ``` sudo apt install dh-make sudo apt install build-essential zlib1g-dev libbz2-dev liblzma-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev tcl-dev tk-dev autoconf-archive python2-minimal systemtap-sdt-dev ``` dh-make 用于创建 deb 包,而其它的都是 python 的构建依赖(3.9~3.13)。新版本的 python 可能变更其依赖,请参考其文档做相应调整。 debian 11 及以下,dh 的部分工具(`dh_clean`)仍然依赖 python2,所以需要安装 python2-minimal ;debian 12+ 去掉了 python2,不必安装。 systemtap-sdt-dev 用于支持 python 的 dtrace 功能( `configure --with-dtrace`)。但在 3.13 遇到编译错误,尚未成功。 ### autoconf ``` apt download autoconf Get:1 https://mirrors.tuna.tsinghua.edu.cn/debian bookworm/main amd64 autoconf all 2.71-3 [332 kB] ``` ``` dpkg -i ./autoconf_2.71-3_all.deb ``` ## 本项目已支持的 python 版本介绍 本项目产出的 deb 包按安装位置分两个系列: * all-in-one : 例如 python3.11-all-in-one-3.11.4 。此系列安装到 /opt 下(如果要直接在命令行中使用,需要将 /opt/bin 目录加入 PATH 环境变量)。除了明确指出冲突以外,可以同时安装多个,也可以与系统自带的 python deb 包共存,即使次要版本相同。此系列为静态链接,没有 libpython3.X.so 文件。 * sys-all-in-one :例如 python3.6-sys-all-in-one-3.6.15 。此系列安装到 /usr 下。不能与系统自带的同主、次版本的 python deb 包共存,而是替代它们(参考其 `debian/control` 文件)。此系列为动态链接(`--enable-shared`),提供 libpython3.X.so 文件。 本项目也包括自由线程版(3.13开始支持),带`t`标志,例如 python3.13t-all-in-one-3.13.0 。自由线程版与非自由线程版(python3.13-all-in-one-3.13.0)冲突,无法同时安装。 ## 编译本项目已支持的 python 版本 如果使用容器/虚拟机作为构建环境,只有 4、5 步需要在构建环境中执行,其它步骤也可在宿主机中执行。 1. 从 python 官网下载 python 的源码,例如 `Python-3.13.0.tar.gz` ,重命名/符号链接为 `<包名>_<版本号>.orig.<扩展名>` ,例如 `python3.13t-all-in-one_3.13.0.orig.tar.gz` ,存放到此项目根目录下。 2. 解压源码到本仓库的对应版本的目录下: 在 `python3.13t-all-in-one-3.13.0/` 下: ``` tar -xvf ../python3.13t-all-in-one_3.13.0.orig.tar.gz --strip-components=1 # 如果是 .tar.xz 文件,则用此命令: # xz -dc ../python3.13t-all-in-one_3.13.0.orig.tar.xz | tar -xv --strip-components=1 ``` 如果源码包里顶层目录形如 `Python-3.13.0`,则加上 `--strip-components=1` 以去掉这层目录,否则不必。 3. 在版本号中加入构建环境信息: 修改 `python3.13t-all-in-one-3.13.0/changelog`,在第一行的版本号 `3.13.0-1` 后面追加 `+deb12`,表示构建环境为 debian 12(如果构建环境是其它,可做相应修改)。改完后,这一行为 `python3.13t-all-in-one (3.13.0-1+deb12) unstable; urgency=medium`。 这个修改不要提交到版本控制中。 4. 生成 configure 文件: 如果 `python3.13t-all-in-one-3.13.0/configure` 已存在,则跳过此步。 否则生成 configure 文件,在 `python3.13t-all-in-one-3.13.0/` 下: ``` autoreconf # 或者 autoreconf -ivf -Werror ``` 对一个源码目录只需要做一次。 5. 编译 deb 包: 在 `python3.13t-all-in-one-3.13.0/` 下: 设置编译选项: ``` export DEB_BUILD_OPTIONS="nocheck nobech nopgo" export CFLAGS="-O1" # 可选 ``` nocheck: 不跑测试 nobech: 不跑性能测试 nopgo: 不做 profile guided optimizition CFLAGS="-O1": 设置C编译器优化级别为1。默认值一般是2。有的组合(gcc-12_12.2.0-14 和 debian12 和 python-3.6.15)需要降低,见后面“版本特定的问题”。 编译: ``` dpkg-buildpackage --no-sign --jobs=8 --no-pre-clean ``` 因为第一次编译时,Makefile 还不存在,所以无法 clean,要加上 --no-pre-clean 选项;以后的编译可以不加 --no-pre-clean ,如果想从头来一遍。 如果成功,会生成 `../python3.13t-all-in-one_3.13.0-1_amd64.deb` 和 `../python3.13t-all-in-one-dbgsym_3.13.0-1_amd64.deb` 文件。 6. 验证: 可以查看 .deb 内容是否正确: ``` dpkg-deb -c ../python3.13t-all-in-one_3.13.0-1_amd64.deb # 列出包含的文件 dpkg-deb -I ../python3.13t-all-in-one_3.13.0-1_amd64.deb # 显示元数据 ``` 如果出现编译错误,先考虑清除编译产生的临时文件(`make clean`),然后不带 `--no-pre-clean` 重试。 ## 编译本项目未支持的新的 python 版本 1. 从 python 官网( https://www.python.org )下载 python 的源码,例如 `Python-3.14.0.tar.gz` ,存放位置随意,此处假设放到此项目根目录下。 2. 在此项目根目录下创建 `python3.14t-all-in-one-3.14.0/` 目录。其中 python3.14t-all-in-one 是包名,3.14.0 是版本号。 3. 执行 dh-make ,生成 debian 配置文件: 在 `python3.14t-all-in-one-3.14.0/` 下: ``` dh_make -f ../Python-3.14.0.tar.gz ``` 第一个问题回答s(single)。 这会创建 `python3.14t-all-in-one-3.14.0/debian/` 目录以及其下的配置文件。 4. 修改 `python3.14t-all-in-one-3.14.0/debian/` 目录下的 `control`、`rules`、`changelog` 文件。参照已有的 `control`、`rules`、`changelog` 进行修改即可,除了包名、版本号、日期,其它都可以保持一致。 * 如果新版本的 python 构建依赖有变更,则修改 `control` 文件的 `Build-Depends:` 字段。 * 如果新版本的 python 的 configure 参数有变更,则修改 `rules` 文件的 `override_dh_auto_configure:` 字段。 然后,按上面“编译本项目已支持的 python 版本“的方法编译即可。 ## 版本特定的问题 ### python3.6 * configure 没有 --disable-test-modules 选项。 * 可能需要降低 gcc 编译器的优化级别,否则生成的 python 可执行文件会有bug,在执行 dpkg-buildpackage 时, `./python -E -m ensurepip $ensurepip --root=...` 命令会出现 Segmentation fault ,导致生成 deb 失败。 这个问题在 gcc-12_12.2.0-14 和 debian12 和 python-3.6.15 的组合下观察到,需要把优化级别降低到 -O1 或更低来避免。 应在执行 dpkg-buildpackage 前执行 `export CFLAGS="-O1"`(在 rules 文件中设置 CFLAGS 无效) 。