杰瑞科技汇

OpenWrt如何编译Python?

核心概念:交叉编译

在 OpenWrt 上编译 Python,最关键的一点是 交叉编译,这意味着你在一个强大的开发主机(通常是 x86_64 的 Linux 或 macOS)上,编译出能在目标 OpenWrt 设备(通常是 ARM, MIPS 等架构)上运行的 Python 可执行文件和库。

OpenWrt如何编译Python?-图1
(图片来源网络,侵删)

你需要使用 OpenWrt 的 SDK (Software Development Kit),它包含了所有必要的编译器、工具链和库头文件,让你的主机能够“模拟”目标 OpenWrt 设备的编译环境。


使用 OpenWrt SDK 进行交叉编译(推荐)

这是最标准、最灵活的方法,可以让你编译出任意你想要的 Python 版本和扩展。

第 1 步:准备工作

  1. 一台开发主机

    • 强烈推荐 Linux (如 Ubuntu, Debian),macOS 也可以,但需要额外配置一些工具,Windows 下的 WSL2 也是一个不错的选择。
    • 确保主机已安装 git, make, gcc, g++, binutils, patch, findutils, gzip, unzip, bzip2, python3 等基本构建工具。
  2. 确定你的 OpenWrt 版本和架构

    OpenWrt如何编译Python?-图2
    (图片来源网络,侵删)
    • 版本:你需要下载与你 OpenWrt 路由器固件完全相同版本的 SDK,如果你的路由器运行的是 OpenWrt 22.03.2,你就必须下载 22.03.2 的 SDK。
    • 架构:你需要知道你路由器的 CPU 架构,常见的有:
      • arm_cortex-a7_neon-vfpv4 (ARMv7, 如 Raspberry Pi 2/3, 很多老旧路由器)
      • arm_cortex-a9_vfpv3-d16 (ARMv7, 一些高性能路由器)
      • aarch64_cortex-a53 (ARMv64/Aarch64, 如 Raspberry Pi 3/4/5, 新款路由器)
      • mipsel_24kc (MIPS, 如老旧的 TP-Link 路由器)
      • x86_64 (如果你的 OpenWrt 运行在 x86 虚拟机或路由器上)

    你可以通过 SSH 登录路由器,运行 uname -m 来查看架构。

第 2 步:下载和解压 SDK

  1. 下载 SDK: 访问 OpenWrt 官方下载页面,选择你的版本,然后找到 "SDK" 部分,下载对应架构的 tar.xz 文件。

    下载 OpenWrt 22.03.5 的 ARMv7 SDK:

    # 创建一个工作目录
    mkdir -p ~/openwrt-python-workspace
    cd ~/openwrt-python-workspace
    # 下载 SDK (请替换为实际的下载链接)
    wget https://downloads.openwrt.org/releases/22.05.3/targets/ath79/generic/openwrt-sdk-22.05.3-ath79-generic_gcc-11.3.0.Linux-x86_64.tar.xz
  2. 解压 SDK

    OpenWrt如何编译Python?-图3
    (图片来源网络,侵删)
    tar -xvf openwrt-sdk-*.tar.xz
    # 进入 SDK 目录
    cd openwrt-sdk-*

    解压后,你会看到一个结构清晰的目录,其中最重要的是 staging_dir/toolchain/

第 3 步:配置 SDK 和编译环境

  1. 设置环境变量: 为了方便后续操作,强烈建议将 staging_dir 下的工具链路径添加到 PATH 中,这样你就可以直接使用 gcc, python 等命令,而无需每次都输入完整路径。

    # 将下面的路径替换成你自己的 SDK 路径
    export PATH=$(pwd)/staging_dir/toolchain-*/bin:$PATH

    你可以将这行命令添加到 ~/.bashrc~/.zshrc 中,使其永久生效。

  2. 验证工具链: 运行以下命令,确保你正在使用正确的交叉编译工具。

    # 查看编译器版本,应该能看到目标架构,mipsel-openwrt-linux-
    gcc --version

第 4 步:下载并编译 Python 源码

  1. 下载 Python 源码: 在 SDK 目录下,创建一个 python-build 文件夹,并下载你需要的 Python 版本源码(Python 3.9)。

    mkdir python-build
    cd python-build
    wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz
    tar -xvf Python-3.9.18.tgz
    cd Python-3.9.18
  2. 配置编译选项: 这是最关键的一步,你需要告诉 Python 的 configure 脚本如何进行交叉编译。openwrt-sdk 提供了一个非常方便的 config 脚本。

    # 返回到 SDK 的根目录
    cd ../../
    # 运行 configure 脚本
    # --host: 指定目标平台
    # --build: 指定当前构建平台 (通常是 x86_64-linux-gnu)
    # --prefix: 指定安装路径 (推荐使用 staging_dir)
    ./python-build/Python-3.9.18/configure \
        --build=$(./config.guess) \
        --host=$(./staging_dir/toolchain-*/bin/*-openwrt-linux-gcc --print-multiarch) \
        --prefix=$(pwd)/staging_dir/usr \
        --enable-optimizations \
        --disable-ipv6 \
        --with-lto
    • --host: 这个参数告诉编译器,最终生成的程序是为哪个平台准备的。$(./staging_dir/toolchain-*/bin/*-openwrt-linux-gcc --print-multiarch) 会自动帮你生成正确的目标平台字符串,如 mipsel-openwrt-linux
    • --prefix: 指定 Python 安装的位置,我们将其安装到 staging_dir/usr,这样所有编译出的文件都会被集中管理。
  3. 编译和安装

    # 使用 -j 参数可以加快编译速度,通常使用 CPU 核心数
    make -j$(nproc)
    make install

    编译完成后,你可以在 staging_dir/usr/bin 下找到 python3pip3 的可执行文件,它们是为你的目标设备交叉编译好的。

第 5 步:部署到 OpenWrt 设备

  1. 打包文件: 将编译好的 Python 文件打包,最简单的方式是复制 staging_dir/usr 目录。

    # 回到 SDK 根目录
    cd ..
    # 创建一个用于传输的目录
    mkdir -p python-for-openwrt/usr
    # 复制编译好的文件
    cp -r staging_dir/usr/* python-for-openwrt/usr/
    # 打包
    tar -czf python-for-openwrt.tar.gz -C python-for-openwrt .
  2. 传输和安装

    • python-for-openwrt.tar.gz 文件通过 scp 或其他方式传输到你的 OpenWrt 设备上。
    • SSH 登录到 OpenWrt 设备,解压文件到 /usr 目录下。(注意:这会覆盖掉系统原有的 Python,请谨慎操作!)
      # scp user@your_host:/path/to/python-for-openwrt.tar.gz ./
      # tar -xzf python-for-openwrt.tar.gz -C /
  3. 验证: 在 OpenWrt 设备上运行:

    /usr/bin/python3 --version
    # 应该显示 Python 3.9.18
    /usr/bin/pip3 --version

使用 OpenWrt 官方源 opkg 安装(最简单)

如果你对 Python 版本没有特殊要求,只是想快速使用,这是最简单的方法。

  1. 更新软件列表: SSH 登录 OpenWrt 设备,运行:

    opkg update
  2. 安装 Python: OpenWrt 官方源提供了 python3python3-pip 等包。

    opkg install python3 python3-pip python3-setuptools
  3. 验证

    python3 --version
    pip3 --version

缺点

  • 版本可能非常旧(OpenWrt 19.07 默认是 Python 3.7)。
  • 某些 Python 库可能因为缺少依赖而无法通过 pip 安装。

在 OpenWrt 上直接编译(不推荐)

如果你的 OpenWrt 设备性能强大(如拥有 ARMv/Aarch64 CPU 和大内存),并且你愿意牺牲大量时间,也可以直接在设备上编译。

# 1. 安装编译依赖
opkg update
opkg install gcc g++ make python3 python3-setuptools
# 2. 下载 Python 源码
cd /tmp
wget https://www.python.org/ftp/python/3.9.18/Python-3.9.18.tgz
tar -xvf Python-3.9.18.tgz
cd Python-3.9.18
# 3. 配置、编译、安装
# --prefix 可以指定一个不冲突的路径,/opt/python3
./configure --prefix=/opt/python3 --enable-optimizations
make -j$(nproc)
make install

缺点

  • 极其耗时:在路由器上编译一个完整的 Python 可能需要数小时甚至更久。
  • 设备性能要求高:容易因内存或 CPU 不足而失败。
  • 不推荐:除非设备性能过剩,否则强烈建议使用方法一。

常见问题与解决

  1. ModuleNotFoundError: No module named '_ctypes': 这是因为 Python 的 _ctypes 模块需要外部库 libffi 的支持,你需要先在 SDK 中交叉编译 libffi,然后在配置 Python 时指定其路径。

    # 在 SDK 中编译 libffi
    cd feeds/packages/utils/
    git clone https://github.com/openwrt/packages.git -b openwrt-22.03 . # 确保在正确的分支
    # 或者直接从 feeds 中拉取
    ./scripts/feeds update -a
    ./scripts/feeds install libffi
    make menuconfig # 确保勾选了 libffi
    make package/utils/libffi/compile -j$(nproc)
    make package/utils/libffi/install
    # 重新配置 Python,添加 --with-system-ffi 参数
    ./python-build/Python-3.9.18/configure ... --with-system-ffi ...
  2. pip 安装包失败:error: Microsoft Visual C++ 14.0 is required: 这个错误只会在 Windows 主机上发生,请确保你使用的是 WSL2 或 Linux 虚拟机。

  3. pip 安装包失败:could not find a setup script: 这通常意味着你尝试安装的包不是纯 Python 代码,而是包含了需要编译的 C/C++ 扩展,你需要确保这个包有针对你目标架构的预编译二进制包(wheel)。

    • 解决方案:在主机上,使用 pip--platform--target 选项,从 https://packages.openwrt.org/ 或 PyPI 下载预编译的 .whl 文件,然后将其传输到 OpenWrt 设备上安装。
方法 优点 缺点 适用场景
SDK 交叉编译 灵活可控,可编译任意版本和扩展,性能最佳 步骤较多,需要准备环境和 SDK 强烈推荐,尤其是需要特定版本或复杂依赖库时
opkg 安装 最简单快捷,无需编译 版本老旧,扩展可能安装失败 只需要一个基础可用的 Python,对版本无要求
设备上编译 无需主机,直接编译 极其耗时,设备性能要求高,风险高 设备性能非常强大,且无法使用 SDK 的特殊情况

对于绝大多数用户来说,方法一(使用 SDK 交叉编译) 是最佳实践,虽然前期设置需要一些时间,但它能给你带来最大的灵活性和最终的稳定性能。

分享:
扫描分享到社交APP
上一篇
下一篇