为 ARM 跨编译

注意

此处的资料不幸仅具有历史价值。Scratchbox 已经不再可用。但是,似乎可以使用 chroot 和 setarch linux32 pypy rpython/bin/rpython ... 在 aarch64 机器上进行 ARM32 的编译。

在这里,我们描述了使用 RPython 编译器将解释器编译为目标 ARM 所需的设置和步骤。

要将 RPython 程序编译为 ARM,我们可以按照正常的编译步骤在 ARM 设备上直接编译。不幸的是,这在大多数 ARM 机器上实际上不可行。另一种方法是使用交叉编译工具链进行跨编译。

要进行跨编译,我们在功能更强大的(通常是 x86)机器上运行编译,并使用交叉编译器编译生成的 C 代码,从而为 ARM 生成二进制文件。这样做时存在一些限制。特别是,我们目前仅支持 Linux 作为编译主机和目标平台(在 Ubuntu 上测试)。此外,我们需要一个 32 位环境来运行编译。这可以在 32 位主机上或在 32 位 chroot 中完成。

需求

从基于 Linux 的主机跨编译到基于 ARM 的 Linux 目标所需的工具有

  • PyPy 的检出(默认分支)。
  • GCC ARM 交叉编译器(在 Ubuntu 上是 gcc-arm-linux-gnueabi package),但其他工具链也应该可以工作。
  • Scratchbox 2,一个交叉编译引擎(scratchbox2 Ubuntu 包)。
  • 32 位 PyPy 或 Python。
  • 并且需要安装以下(或相应的)包来创建基于 ARM 的 chroot
    • debootstrap
    • schroot
    • binfmt-support
    • qemu-system
    • qemu-user-static
  • 除了常规编译所需的依赖项外,还需要上述依赖项,此处列出

创建基于 Qemu 的 ARM chroot

首先,我们需要创建一个 rootfs,其中包含编译 PyPy 或其他解释器所需的包和依赖项。我们将假设这些文件将放置在 /srv/chroot/precise_arm 中。

通过调用以下命令创建 rootfs:

mkdir -p /srv/chroot/precise_arm
qemu-debootstrap --variant=buildd --arch=armel precise /srv/chroot/precise_arm/  http://ports.ubuntu.com/ubuntu-ports/

接下来,将 qemu-arm-static 二进制文件复制到 rootfs 中。

cp /usr/bin/qemu-arm-static /srv/chroot/precise_arm/usr/bin/qemu-arm-static

为了更轻松地配置和管理,我们将创建一个指向 rootfs 的 schroot。我们需要在 /etc/schroot/schroot.conf 中的 schroot 配置文件中添加一个配置块(如下所示)。

[precise_arm]
directory=/srv/chroot/precise_arm
users=USERNAME
root-users=USERNAME
groups=users
aliases=default
type=directory

要验证 chroot 中的所有内容是否正常工作,运行 schroot -c precise_arm 应该会启动一个在 schroot 环境中运行的 shell,并使用 qemu-arm 执行 ARM 二进制文件。在 chroot 中运行 uname -m 应该会产生类似 armv7l 的结果。表明我们正在模拟 ARM 系统。

以 root 用户身份启动 schroot,以便配置 apt 源并安装以下包

schroot -c precise_arm -u root
echo "deb http://ports.ubuntu.com/ubuntu-ports/ precise main universe restricted" > /etc/apt/sources.list
apt-get update
apt-get install libffi-dev libgc-dev python-dev build-essential libncurses5-dev libbz2-dev

现在所有依赖项都应该就绪,我们可以退出 schroot 环境。

配置 scratchbox2

要配置 scratchbox,我们需要 cd 到之前创建的 rootfs 的根目录。从那里,我们可以调用 sb2 配置工具,这些工具将把当前目录作为 scratchbox2 环境的基本目录。

cd /srv/chroot/precise_arm
sb2-init -c `which qemu-arm` ARM `which arm-linux-gnueabi-gcc`

这将创建一个名为 ARM 的基于 scratchbox2 的环境,该环境将 scratchbox 内部的 gcc 调用映射到 scratchbox 外部的 arm-linux-gnueabi-gcc。现在,我们应该已经拥有了一个可用的交叉编译工具链,并且可以开始为 ARM 跨编译程序了。

编译

完成所有预备步骤后,我们现在应该能够为 ARM 跨编译程序了。您可以使用此最小目标在将其应用于更大的项目之前测试您的设置。

在启动编译器之前,我们需要设置两个环境变量,以便编译器知道如何使用 scratchbox 环境。我们需要将 SB2 环境变量设置为指向 rootfs,并且 SB2OPT 应包含 sb2 命令的命令行选项。如果我们的 rootfs 在 /srv/chroot/precise_arm 文件夹中,并且 scratchbox 环境称为“ARM”,则变量将定义如下。

export SB2=/srv/chroot/precise_arm
export SB2OPT='-t ARM'

设置完成后,您可以调用编译器。例如,保存此文件

def main(args):
    print "Hello World"
    return 0

def target(*args):
    return main, None

并调用编译器

pypy ~/path_to_pypy_checkout/rpython/bin/rpython -O2 --platform=arm target.py

如果一切正常,这应该会生成一个 ARM 二进制文件。在 ARM chroot 或 ARM 设备上运行此二进制文件应会产生输出 "Hello World"

要使用 jit 编译完整的 python pypy 解释器,您可以 cd 到 pypy/goal 并调用

pypy <path to rpython>/rpython/bin/rpython -Ojit --platform=arm targetpypystandalone.py